[Gc] Determine the requested size of a memory block

Boehm, Hans hans.boehm at hp.com
Thu Apr 22 16:17:38 PDT 2010


> From: Ivan Maidanski
> Sent: Thursday, April 22, 2010 2:47 AM
> To: Christian Gudrian
> Cc: gc at napali.hpl.hp.com
> Subject: Re[2]: [Gc] Determine the requested size of a memory block
> 
> 
> Thu, 22 Apr 2010 11:05:38 +0200 Christian Gudrian 
> <christian at gudrian.org>:
> 
> > Am 22.04.2010 09:43, schrieb Ivan Maidanski:
> > 
> > > In theory, it's possible to adjust hb_sz (returned by GC_size) to 
> > > have a byte granularity (with some negligible performance loss).
> > 
> > I certainly do not want to fumble around in the innards of 
> the collector.
> > Instead I now provide a custom implementation of the array 
> new operator:
> > 
> > // -----------------------------------------------------------------
> > inline void * operator new[] (size_t size,
> >                               GCPlacement gcp,
> >                               GCCleanUpFunc cleanup = 0,
> >                               void * clientData = 0) {
> >    size_t * ptr = (size_t *) ::operator new (size + sizeof 
> (size_t), 
> >                                              gcp, cleanup, 
> clientData);
> >    *ptr++ = size;
> 
> So, all array pointers are displaced (and 
> all_interior_pointer should be on, and to call some GC 
> functions (like GC_register_finalizer) you have to call 
> GC_base) - not a good idea, IMHO.
You could also deal with this through GC_register_displacement() and by adjusting the pointer before you pass it to something like GC_register_finalizer().

> 
> >    return ptr;
> > }
> > // -----------------------------------------------------------------
> > 
> > The length() function looks like this:
> > 
> > // -----------------------------------------------------------------
> > template<class T>
> > size_t length (T * array)
> > {
> >    size_t * ptr = (size_t *) GC_base ( (void *) array);
> 
> This won't work correctly in case of GC_DEBUG.
I'm also surprised this works.  Why not just ptr = ((size_t *)array) - 1 ?

> 
> >    assert(ptr);
> >    return *ptr / sizeof (T);
> > }
> > // -----------------------------------------------------------------
> > 
> > Now it's possible to use arrays this way:
> > 
> > char * c = new (PointerFreeGC) char[123]; for (int i = 0; i < 
> > length(c); i++)
> 
> I think, length() is quite convenient.
> 
> Hmm... I'd prefer GC_size() to have byte granularity (and 
> exclude GC debug header) to be usable in this case.
> 
> Hans -
> what do you think of this topic?
That seems potentially expensive.  We only store the size in the hblk header, i.e. it's shared between all objects in an hblk.  For that size to be accurate to the byte, we'd have to make sure that e.g. 62 and 63 byte objects are in different hblks.  I think that would add significant fragmentation for small heaps and adversely affect cache locality.

If someone has the time to invest here, it might be worth thinking about making the size optionally accurate to GC_GRANULE_BYTES and making GC_GRANULE_BYTES = 1 do something reasonable, so that you could optionally configure the collector to have this work.  But I think there are many bug-introduction possibilities there, particularly when it comes to GC_realloc.  (I'm not sure whether we need to worry about alignment issues, since objects should generally have a size that is a multiple of their alignment requirements.  But I may be overlooking some more fundamental issues.)

I suspect that adding an explicit size to the object is far easier.  Gcj also does that for Java arrays.

Hans
> 
> > {
> >    char value = c[i];
> >    // ...
> > }
> > 
> > Christian
> 
> _______________________________________________
> Gc mailing list
> Gc at linux.hpl.hp.com
> http://www.hpl.hp.com/hosted/linux/mail-archives/gc/
> 


More information about the Gc mailing list