What's the go with the GC these days?
Neia Neutuladh
neia at ikeran.org
Sat Jan 5 23:12:52 UTC 2019
On Sat, 05 Jan 2019 14:05:19 -0800, Manu wrote:
> I'm somewhere between a light GC user and a @nogc user, and I don't
> really know much about where we're at, or much about start-of-the-art GC
> in general.
I use the GC unabashedly and only try to make sure I reuse memory when
it's reasonably convenient. I've also looked into GC a bit.
> How much truth is in here?
D uses a simple GC. Simple means easy to reason about. It's also got
better tools to stress the GC less. But one thing it could get that would
be interesting is a thread-local GC. (You'd have a stop-the-world phase
that happened infrequently. Casting something to shared would pin it in
the thread it was allocated from.) Another thing that it probably should
have is a precise pointer map. For small allocations, that probably
wouldn't be a net benefit -- the overhead of storing a typeinfo pointer by
each allocation isn't awesome. But for mid-size arrays and larger, it could
be helpful.
The Boehm collector is more advanced than D's GC. It's (at least
optionally) generational with write barriers.
Go is a GC-heavy language, only a bit less so than Java, so its GC
performance makes a huge difference.
> What is this business about write barriers making the GC fast? Is that
> actually fact, or are there other hurdles?
With D's GC, your normal operation is unimpeded; you're not running GC
code at all unless you allocate. This makes it easy to reason about the
GC. However, the GC must then scan all your memory to determine if you
have pointers to a memory allocation.
With write barriers, any write to any piece of memory that might contain
pointers can be intercepted. The fast-but-inaccurate way is to use the
MMU: mark that memory readonly and set up a fault handler. The handler
will mark the memory read-write and enqueue that page of memory for
scanning. The GC must also maintain a graph of which pages of memory point
to which other pages of memory.
> Is the claim that write-barriers generally slow your runtime performance
> significant? And if it is, is it possible/reasonable to control the
> places where they are emit?
You can control it a little. Any time you think you might possibly need to
write to a pointer, you do a fake write to it in advance. An optimizing
compiler might try to remove those writes, so maybe define it in assembly.
This is hideously cumbersome.
Alternatively, you could manually mark a segment of memory for the GC to
clear the write barrier, and it will have to scan that region next
collection.
> Can @nogc be used to inhibit write barriers in code that we know doesn't
> interact with the GC, such that we have control over that loss of perf?
The point of a write barrier is to record where pointers might have
changed. @nogc doesn't mean that you can't change a pointer, so it can't
sidestep write barriers. Not unless you want both memory leaks and use-
after-free bugs.
> Is progress possible, or is the hard reality that the language is just
> designed such to be resistant to a quality GC, while the ecosystem sadly
> tends to rely on it?
Three things about D make it harder to make a good GC for it:
* unaligned pointers
* unions
* externally allocated memory (malloc and friends)
We've pretty much addressed malloc by telling people to manually add and
remove malloced memory from what the GC scans. A union is pretty much just
a pointer that might not be valid. Unaligned pointers just kind of suck.
More information about the Digitalmars-d
mailing list