logo       

Re: gencgc performance and soft-real time: msg#00308

lisp.cmucl.devel

Subject: Re: gencgc performance and soft-real time

Luke Gorrie <luke@xxxxxxxxxxxx> writes:

> What 'scavenge' does is update pointers to objects that were moved
> during GC. To do this it rummages through and updates objects in
> generations other than the one that was collected and objects in
> "static space". There is an optimization here: a "write-barrier" is
> used to keep track of objects in other generations that have not
> been modified since the last GC. Those objects can be skipped when
> scavenging, because they can't point to freshly moved object.

<aside>
Let me put that a bit differently, maybe it's helpful.

Leaving ambiguous roots and generations out for a moment, gencgc is a
copying GC, which copies from-space objects to a new space. GC starts
by scavenging roots, which copies from-space objects referenced from
places known to potentially contain references to live from-space
objects. Each time scavenge copies an object, it leaves a forwarding
pointer behind in the from-space object pointing to the new-space
copy. When scavenge later scavenges a reference to a from-space
object containing such a forwarding pointer, it updates the reference
to point to the copy in new-space.

The write-barrier is an optimization of the so-called remembered set,
that is, the set of references from older to younger generations.
Without some optimization of the remembered set, one would have to
scan all of the older generations to find references to live
from-space objects.
</aside>

> The trouble is that the write-barrier optimization is only used for
> other generations, and not objects in static space -- so all static
> objects are scavenged every time. This is typically several megabytes
> of data. This is where the GC is spending all that time!

Could well be. Since scavenging costs per Mb should be more or less
constant, I'd expect this to depend on the ratio of the size of static
space to the size of what else needs to be scavenged, and I'd say the
latter mostly depends on how many live objects there are. If there
are few live objects, static space scavenging costs probably outweigh
other scavenging costs.

> That's my theory anyway. I've checked by getrusage+printf and by
> observing the effect of scavenging static space multiple times per GC,
> and both showed that scavenging static space was the "hot
> spot". Because I'm not actually modifying objects in static space (as
> far as I know), it seems likely we could optimize away all this
> scavenging and drastically shorten GC times.
>
> My first thought was to put a write barrier over static space. While I
> was still struggling to make that work (but never did), Dan Barlow
> suggested a more holistic approach -- why do we have so many objects
> in static space, and could we not put them into a "tenured" generation
> that doesn't get GC'd instead? That would give us a write-barrier for
> free.

That would be nice, indeed. If one does, one should probably move
static space in the virtual address space so that one doesn't end up
with an overly large page table, but I don't see anything making that
impossible in principle, at least at present.

> Alas, my attention span was not great enough to read enough of
> gencgc.c and purify.c to understand the full picture, so this is as
> far as I've gotten.
>
> Is anyone able to shed some more light?

Any specific questions? I keep forgetting details, but maybe I can
help with one or the other thing.

> (Wouldn't it be wonderful if a little optimization rendered the common
> wisdom that "if response time matters then you mustn't cons"
> obsolete?)

He, use dynamic-extent, that's why I wrote it :).




<Prev in Thread] Current Thread [Next in Thread>
Google Custom Search

News | FAQ | advertise