struct destructor

cc cc at nevernet.com
Sun May 16 08:04:06 UTC 2021


On Saturday, 15 May 2021 at 18:24:19 UTC, Alain De Vos wrote:
> Thanks, good idea but,
> It does not initiate a GC cycle or free any GC memory.

Personally I wish D would re-implement "delete" and make it "just 
work" like one would assume, but from what I've seen there have 
been many many debates on that and it isn't going to happen.  If 
the goal is to absolutely squeeze the GC back down after using 
new or dynamic arrays, I find destroy + GC.free often fails to do 
the trick (e.g. GC.stats.usedSize remains high).  For whatever 
reason (I glanced at the code but haven't found the magic yet), 
the deprecated __delete does a more thorough job of making sure 
that memory actually gets "given up" on a collection cycle 
(particularly if you invoke it manually with `GC.collect(); 
GC.minimize();`.  Presumably this isn't a desirable coding 
behavior, though.  In my field (games), I do do something like 
this after initially loading the data to free up all the unused 
clutter and scaffolding, but it's very slow to call it every 
frame if you've been using the GC to create and delete game 
entities.  So like Adam says, standard C malloc/free are probably 
the best way to go in this case.
```d
import core.stdc.stdlib;
import core.lifetime;
class Foo {}
auto foo = cast(Foo) malloc(__traits(classInstanceSize, Foo));
emplace!Foo(foo, /*constructor args*/);
// ...
destroy(foo);
free(cast(void*)foo);
```

Another alternative is something like the memutils library:
https://code.dlang.org/packages/memutils
```d
class Foo {}
auto foo = ThreadMem.alloc!Foo(/*constructor args*/)
ThreadMem.free(foo); // calls destroy for you, but can still 
destroy manually
```
You'll still need to be very careful about any GC mem that gets 
allocated within a class like this as it can get lost into the 
ether and cause permanent bloat.

I've been doing a lot of iteration tests lately across a whole 
bunch of different memory management solutions and the state of 
discrete memory management in D for gaming applications is.. not 
great.  I love D, but for all that it's designed to help reduce 
programmer error, it goes the opposite way once you start 
breaking free of the GC and having to be extra careful tiptoeing 
around its edges.  Unfortunately I don't like doing the pure 
@nogc/betterC route either, the GC is still really handy to have 
when you need it (and are aware that it's being used!), but GC 
collections during high intensity gaming are unacceptable (and 
deferring them to some later point doesn't help much either).

Fair warning, I'm not one of the D elite with a deep guru-level 
knowledge of just precisely how everything is operating under the 
hood, so part of this may come down to learning better practices, 
but a problem I see IMO is a perceived lack of support or 
sympathy for coders who want to use the GC when it's nice, but 
not have it smack them in the face when it isn't.  Even with the 
various articles and forum threads explaining D's memory options, 
there's still a general air of "You really should just be using 
the GC, so enjoy your no-man's land, you're on your own."  
Whether this is only an unfair perception and matter of 
documentation, or something that actually needs to be addressed 
in the language, is beyond simply me to decide, but I think a lot 
of outsiders coming into D may run into the same situation.


More information about the Digitalmars-d-learn mailing list