The GC could be improved by generating extra code when pointer accesses are made, so the GC can keep track of writes to GC allocated memory. This makes the GC faster and more effective, at the expense of slower generated code.
It is a worthwhile tradeoff for fully GC languages like Java. But it isn't worthwhile for D, which uses GC here and there and a lot of non-GC pointers and allocations. D trades things off in the other direction - faster runtime code generation, at the cost of a slower GC.
The more pointers you need to scan, the slower it becomes, and it'll stop all threads
It's fine for a compiler or a cli tool, but it's very bad for anything that runs forever and needs to scale (server and games, specially networked games where the world and number of entities is not fixed) you then need to think about managing your memory and working around the GC a lot; then you think about yourself, why use GC at all..
D needs invest more into non GC stuff and making the GC trully optional, make it possible to link the GC away if you don't need it, make the runtime less dependent on GC (ability to statically make GC usages assert such as 'new', rework associative array, and cleanup the runtime from requiring GC, thread, socket etc etc etc)
I use D everyday, i know how to deal with that kind of issue, but new people don't, and they might be turned off the day they need to workaround GC issues
> D, which uses GC here and there and a lot of non-GC pointers and allocations
Won't this depend on the programming style used? If the programmer makes heavy use of functional programming, or for that matter Java-style programming, wouldn't that result in a lot of object churn through the GC?
Java does not have stack allocated objects like struct instances. They get allocated via the GC (sometimes the Java optimizer can optimize these to be stack allocated).
Personally, I make very heavy use of stack allocated objects, even for temporary buffers. Stack allocated objects cost nothing to allocate, nothing to free, and (being on the stack) are already in the hot memory cache.
Functional code as usually written in D doesn't have this problem because people are aware of this - most compositions are extremely lazy, allocations are trivial to group together because of allocators in the stdlib
To make it effective, you'd only want it to apply to GC pointers. But the type system does not distinguish between GC pointers and other pointers, making such a mode a rather complex implementation problem.
If you have a struct on the stack, and call member functions, you've got pointers. For an array on the stack, taking a slice of it or looping through it with pointers, you've got pointers. For a variable on the stack, passing it by ref to another function, there are pointers.
It is a worthwhile tradeoff for fully GC languages like Java. But it isn't worthwhile for D, which uses GC here and there and a lot of non-GC pointers and allocations. D trades things off in the other direction - faster runtime code generation, at the cost of a slower GC.