Why I Like D

H. S. Teoh hsteoh at quickfur.ath.cx
Thu Jan 13 17:13:46 UTC 2022


On Thu, Jan 13, 2022 at 10:21:12AM +0000, Stanislav Blinov via Digitalmars-d-announce wrote:
[...]
> Oh there is a psychological barrier for sure. On both sides of the,
> uh, "argument". I've said this before but I can repeat it again: time
> it. 4 milliseconds. That's how long a single GC.collect() takes on my
> machine.  That's a quarter of a frame. And that's a dry run. Doesn't
> matter if you can GC.disable or not, eventually you'll have to
> collect, so you're paying that cost (more, actually, since that's not
> going to be a dry run). If you can afford that - you can befriend the
> GC. If not - GC goes out the window.

?? That was exactly my point. If you can't afford it, you use @nogc.
That's what it's there for!

And no, if you don't GC-allocate, you won't eventually have to collect
'cos there'd be nothing to collect. Nobody says you HAVE to use the GC.
You use it when it fits your case; when it doesn't, you GC.disable or
write @nogc, and manage your own allocations, e.g., with an arena
allocator, etc..

Outside of your game loop you can still use GC allocations freely. You
just collect before entering the main loop, then GC.disable or just
enter @nogc code. You can even use GC memory to pre-allocate your arena
allocator buffers, then run your own allocator on top of that. E.g.,
allocate a 500MB buffer (or however big you need it to be) before the
main loop, then inside the main loop a per-frame arena allocator hands
out pointers into this buffer. At the end of the frame, reset the
pointer. That's a single-instruction collection.  After you exit your
main loop, call GC.collect to collect the buffer itself.

This isn't Java where every allocation must come from the GC. D lets you
work with raw pointers for a reason.


> In other words, it's only acceptable if you have natural pauses
> (loading screens, transitions, etc.) with limited resource consumption
> between them OR if you can afford to e.g. halve your FPS for a while.
> The alternative is to collect every frame, which means sacrificing a
> quarter of runtime. No, thanks.

Nobody says you HAVE to use the GC in your main loop.


> Thing is, "limited resource consumption" means you're preallocating
> anyway, at which point one has to question why use the GC in the first
> place.

You don't have to use the GC. You can malloc your preallocated buffers.
Or GC-allocate them but call GC.disable before entering your main loop.


> The majority of garbage created per frame can be trivially
> allocated from an arena and "deallocated" in one `mov` instruction (or
> a few of them). And things that can't be allocated in an arena, i.e.
> things with destructors - you *can't* reliably delegate to the GC
> anyway - which means your persistent state is more likely to be
> manually managed.
[...]

Of course. So don't use the GC for those things. That's all. The GC is
still useful for things outside the main loop, e.g., setup code, loading
resources in between levels, etc..  The good thing about D is that you
*can* make this choice.  It's not like Java where you're forced to use
the GC whether you like it or not.  There's no reason to clamor to
*remove* the GC from D, like some appear to be arguing for.


T

-- 
The only difference between male factor and malefactor is just a little emptiness inside.


More information about the Digitalmars-d-announce mailing list