[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-serviceability-dev
Subject:    Re: RFR: 8322476: Remove GrowableArray C-Heap version, replace usages with GrowableArrayCHeap
From:       Kim Barrett <kim.barrett () oracle ! com>
Date:       2023-12-22 23:22:24
Message-ID: 300914D8-7893-4859-A32F-3250CF7C3C84 () oracle ! com
[Download RAW message or body]

[Kim Barret wrote:]
> > > pre-existing: There are a lot of non-static class data members that are \
> > > pointers to GrowableArray that seem like they would be better as direct, e.g. \
> > > non-pointers. 
> > > pre-existing: There are a lot of iterations over GrowableArray's that would be
> > > simplified by using range-based-for.
> > > 
> > > I'm not a fan of the additional clutter in APIs that the static memory types \
> > > add. If we had a variant of GrowableArrayCHeap that was not itself dynamically \
> > > allocatable and took a memory type to use internally as a constructor argument, \
> > > then I think a lot of that clutter could be eliminated.  It could be used for \
> > > ordinary data members that are direct GAs rather than pointers to GAs.  I think \
> > > there is a way to do something similar for static data members that are \
> > > pointers that are dynamically allocated later, though that probably requires \
> > > more work. 
> > 
> > On Fri, 22 Dec 2023 13:22:19 GMT, Stefan Karlsson <stefank@openjdk.org> wrote:
> > FWIW, I added the GrowableArrayCHeap and the static memory type. I did that \
> > because there was a perceived need to minimize the memory usage, because we were \
> > going to use an extreme amount of these arrays for one of our subsystems in ZGC. \
> > It later turned out that we really didn't need to squeeze out the last bit of \
> > memory for that use-case. I would really like to get rid of the the static memory \
> > type from GrowableArrayCHeap, and just add it as an instance member.

Currently the basic overhead for a static-MEMTYPE GA is 16 bytes (data
pointer, int length and capacity).  So 16 bytes on 64bit platforms.  Adding
the memory type adds 8 bytes (due to alignment), so 50% increase.  Though it
may not matter for dynamically allocated GAs, since std::max_align_t is
probably at least 32 bytes.  Though I think we seriously overuse dynamic
allocation for GAs.

Does it really matter.  I don't know.

StringDedup uses a lot of GAs. (Though it could use 1/2 as many with some work,
since they are used in pairs that always have the same length and capacity. At
the time I was working on it I was feeling lazy and just used pairs of GAs, with the
intention of coming back to that at some point if it proved to be a significant \
problem.)

> On Dec 22, 2023, at 8:33 AM, Emanuel Peter <epeter@openjdk.org> wrote:
> @stefank Maybe it would then make sense to do that before this change here? Because \
> we will really have to touch all these changes here again for that. 
> @kimbarrett @stefank @jdksjolen
> Or alternatively, we just say that we want to keep the C-Heap functionality inside \
> `GrowableArray`, and simply remove `GrowableArrayCHeap`? Though I honestly would \
> prefer a world where every allocation strategy has its own `GrowableArray*` \
> variant, so that it is clear statically that they cannot be assigned to each other. \
> So my preference would even be to have these: 
> CHeapGrowableArray
> ArenaGrowableArray
> ResourceAreaGrowableArray
> 
> What do you think?

I think having distinct CHeap, Resource, and Arena allocated types would be an
improvement. If we were using std::vector with associated allocators we'd have
something like that. (The allocator type is a template parameter for
std::vector.) Refactoring GA in that direction is certainly possible, and
might be an improvement.

We could also have two variants of CHeap GAs, one with the memtype being a
constructor argument (and possibly different from the memtype used to
dynamically allocate the GA, as is currently the case, although I think that
feature is never used), and a more compact one with a static memtype.

I did some work on HotSpot allocators for standard containers like std::vector
a while ago that could be applied to GA.  It includes support for dynamic and
static memtypes, and shows that isn't hard to do.

I thought about whether this PR should go ahead without some of that stuff in
place. It touches a lot of places that would probably be touched again if we
went in that sort of direction. OTOH, a lot of these same places would
probably need to be touched repeatedly anyway, one way or another. For
example, dealing with what appears to be a large amount of unnecessary dynamic
allocation of GAs would also touch a lot of these places, and I'm suspicious
of combining the type changes and the allocation changes in one PR.

> And how important is it that we do not use `virtual` with `GrowableArray`? Because \
> the implementation and testing is much nastier without it. Is the V-table still \
> such a overhead that we need to avoid it?

I don't think there is any need for virtual functions in GA.


["signature.asc" (signature.asc)]

-----BEGIN PGP SIGNATURE-----

iQIzBAEBCAAdFiEErsON5iYRKpuGOrjBMSl6JxmzxBAFAmWGGiYACgkQMSl6Jxmz
xBBI4xAAuYSMwIqwQPih4DGr+fwABw5BMqsJUCWZRmnnigufGtFY0JZH44EaT6R8
UOH/X71u/FS/+HDAUUZdlfllRjPRAHNjvO8eJJb8Q2U7EhDsHBoP/d+ZNp0y/Kc4
Ps5fpnHEo0PwDwYxNFmSpqGMBcrrksx7pXK61gYJpJ6yyneLHshr946cHaMNMeVX
1vptimiHosfuFAYikwa0arc/vr/vEhw1xXlOot7XYS12Bl1230RGzBN+s0YzmyW/
oYfSah/6bfAAJP/XHBACYmcNdzs4oMNmk5Y0o7ThFzjyGsXVKBMY1E6+dUL4sAxd
YqgUPXWcqZAR881VnM4rw1ORcEdM8l/UhCVwEpLTk4C3UxVPhxgit2N/gCnYJ94/
B3JThpsRkEQspThwuuw876iF/2zQ5o1JyrWWC+oEgF0Q7ZHXW/rC3ygXTv6p/lx7
MYmp8XRVTAjt9DQwQtl0YSWKcoZMmvyq9L2xiTeguo6jkpIq46FP0SbUs2EiTpnP
fC1VjWramFclU9qzW1uXZBfPU8SLR0NGUoBe/2pZZtP9IO6nuCd7ZpkdyZEB79QY
eLrLvAiILpyIJQUMHDb0GEyrhsFM8X8cA7scnKRuR2hj/rghQvsqClM/OOL43xd0
Rg2q1XAgdtIeGtINVgb/dpaqt9E+0TyQkqkqNeKko1nEefpZZWc=
=mYvZ
-----END PGP SIGNATURE-----


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic