Future of memory management in D

tchaloupka chalucha at gmail.com
Wed Nov 17 12:14:46 UTC 2021


On Wednesday, 17 November 2021 at 02:32:21 UTC, H. S. Teoh wrote:
>
> With a GC, you instantly eliminate 90% of these problems.  Only 
> 10% of the time, you actually need to manually manage memory -- 
> in inner loops and hot paths where it actually matters.
>
> GC phobia is completely irrational and I don't see why we 
> should bend over backwards to please that crowd.
>
>
> T

I tell you a story :)

I came from C# so not a GC phobic at all. It's a different 
mindset compared to hardcore C/C++ devs. (just get the shit done 
using some of so many libraries out there).

What I liked (and still like) that D allowed me to do is become 
more low level, more performant, but still be very productive. D 
code also is ofter much shorter and easier to understood (rust 
makes my eyes bleed).

GC allows that and is great for. And I must admit that D had 
broken me in a way that I don't want to use higher level 
languages anymore. I've learned a lot using D through the years.

BUT:

* have you tried to write a shared D lib used from some other 
language from multiple threads? I know that you must 
register/unregister threads in GC, but it just hasn't work for me 
reliably in any way and you would have to track the lifetime of 
the thread in the calling language - not pleasant experience at 
all, no tutorials of how to do that properly that actually works 
- it's some years old 
[experience](https://forum.dlang.org/post/lhgljscvdwjdmxrnpchv@forum.dlang.org) now so maybe something has changed
* as GC is `stop the world` kind, only way to make it to not 
intervene with you and still use it in other places is make a 
thread (with a @nogc function) that is not registered in the GC 
and make some own mechanism to exchange data between GC and @nogc 
threads (as std.concurrency won't help you here)
* GC won't magically stop the leaks. Nowadays one want's to have 
a long running service that just works. But try that with a 
'flagship' vibe-d framework and you probably get 
[this](https://forum.dlang.org/post/pzrszydsqfxyipowoprn@forum.dlang.org) experience
   * I don't like much when GC.stats reports something like: 239MB 
free from 251MB used memory that is a lot of unused space in a 
microservice world (and we had a cases when OS just OOM killed 
the service as it just grows indefinitely regardles there is a 
majority of free space in GC - as GC.stats says)
   * and now figure that out -> after that experience I would 
rather use `asan` than GC with no tools helping to figure that out
   * we have somehow managed to set GC properties in a way that it 
doesn't grow that much and get rid of a lot of small allocations, 
but with a cost you wouldn't expect using the GC
     * one of the cases that caused a lot of unnecessary small 
allocations was something like this `row["count"].as!long` when 
reading the columns from a database. Seems like a totally normal 
way right? But there is much more to it. As it (`dpq2` library) 
uses `libpq` internally that addresses columns by their index, it 
uses C method with `char*` column name to get it and so is using 
`toStringz` that allocates, for every single use of that column 
for every single row being read. You can imagine where it goes 
handling some complex queries on thousands of rows. And that is 
not something that a programmer like 'original me' wants to care 
about, he just wants to use the available libraries and get the 
work done, that is what GC should help with right?
   * there are leaks caused by druntime bugs itself (for example 
https://issues.dlang.org/show_bug.cgi?id=20680)

After those and some other experiences with GC I just became a 
bit GC phobic (I'm ok with GC for CLI tools, scripts, short 
running programs, no problem with that there) and try to avoid it 
as much as I can. But when you want to `get shit done` you can't 
write all on your own, but use the libraries that get you there 
with no much hassle between.

Overall my 2 cents on D state:

* druntime relies too much on the GC
   * no Fiber usable in @betterC or @nogc
   * no Thread usable in @betterC or @nogc
   * etc.
   * I just think that basic blocks we built on should be as low 
level as possible to be generally usable
* druntime and phobos has many `extern(C)` or normal functions 
that aren't `@nogc` albeit they can be (but is's getting better 
with each release thanks to various contributors that cares as 
much as at least report it) - but look at codebases of `mecca` or 
`vibe-d` where they use their own `extern(C)` redefinition due to 
this, or `mecca` has `assumeNoGC` template to workaround missing 
`@nogc` attribute
* std.experimental.allocator
   * still in experimental
   * not usable in `@betterC`
   * shouldn't generally standard library interface use the 
allocators so that caller can actually choose the way it 
allocates?
* preview switches that would stay in preview forever (ie 
`fieldwise`)?
* no `async`/`await` - it's hard to find a modern language 
without it, D is one of them and there doesn't seem to be any 
interest in it by the leadership (it would deserve a workgroup to 
work on it)
   * but I'm afraid even if it would potentially be added to the 
language it would still use the GC as GC is great..
* pure tooling compared to others - I'm using VSCode in linux 
(sorry I'm lazy to learn vim in a way I'd be effective with it), 
it somewhat works, but code completion breaks too often for me 
(I'm used to it over the years, but I can imagine it doesn't look 
good to newcomers)
* dub and code.dlang.org doesn't seems to be too official, and 
being cared about
* it's hard to tell anyone that GC in D is fine when you look at 
techempower benchmark and searching the vibe-d (or anything in D) 
somewhere up where it should be and isn't (event other GC 
languages are much higher there)
* `betterC` seems to becoming an unwanted child and is a 
minefield to use - see 
[bugs](https://issues.dlang.org/buglist.cgi?bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&keywords=betterC%2C%20&keywords_type=allwords&list_id=238210&query_format=advanced&resolution=---)
* I think there are 2 sorts of group in D community - one more 
low level that won't like to use GC much, and GC 'likers', for 
whom GC is just 'good enough'
   * I'm afraid that there can't be consensus of what D should 
look as those groups has different priorities and points of view
   * preferred memory model differs for them too and I'm not sure 
if it's possible in D to make both sides happy (and without 
breaking changes)
* most libraries on code.dlang.org are high level, and mostly 
when you want to use `betterC` or avoid GC, you are on your own. 
That is a problem when you just want to use some component and be 
done (if there is no C alternative or it would mean to write a 
more idiomatic wrapper for it).


More information about the Digitalmars-d mailing list