While you can use D without the garbage collector, you will lose access to a lot of the standard library, which limits the practicality of running without garbage collection.
While you can use D without the garbage collector, you will lose access to a lot of the standard library, which limits the practicality of running without garbage collection.
An advanced GC requires having "write gates" inserted into the generated code. These take away from performance, but in a language like Java that makes very heavy use of the GC, the gain in GC performance outweighs the slower code.
D is not a GC heavy language, even if all you use is the GC, hence it is a poor tradeoff. (For example, in D you can use the stack for a great deal of the routine allocations, whereas in Java these are often done with the GC. Java has optimizations to try and detect when allocations can be done on the stack, but this isn't as effective as proactively putting them on the stack.)
This isn’t strictly true. In particular it is possible to design a GC such that write barriers are implemented in hardware (these days using the mmu not dedicated hardware). It’s also possible to write a (non-incremental non-concurrent non-parallel) gc that uses no write barriers: just stop the world, collect and move.
The mmu-for-write-barrier technique I’ve seen is to keep pointer colour in high bits and map the same physical memory onto n copies of itself in virtual memory (so you don’t need to mask the colour bits away before dereferencing). When the mutator tries to write to a black pointer (or maybe pointers are coloured by whether their targets might have moved?), the gc gets a memory exception and can ensure that the invariants are maintained. The general assumption is that this doesn’t happen very often in most programs. I can’t remember the name of the system I’m thinking of but it’s one of the new GCs being developed for java.
An alternative method to avoid a write barrier is avoiding mutation in your programming language. This makes GC simpler. There are other advantages and disadvantages
> you will lose access to a lot of the standard library
This is incorrect. Not much of it needs the GC anymore.
P.S. click the link to see the spec...
Class destructors can be declared deterministic with the "scope" keyword: https://dlang.org/spec/attribute.html#scope
Scope guards are useful if you cannot change the data type itself.
Your remark, additionally being taught programming on languages that indeed use the GC heap allocations for everything, and on those that allow fine grained control over resources it is usually left for "exercise to the reader", so many don't care and so aren't aware of what they are losing.
If you have real-time needs, then GC is probably out. That includes handling audio and video playback.
Tight memory constraints are another killer argument against GC but that only applies to small embedded devices. Smartphones, desktops, and servers have enough RAM.
The great thing about D is that you can start the easy way with a GC. When real-time or memory become constraints at some point you can selectively adapt parts of your program.
You could say, D wants to provide Python and Rust and everything in between so that you can shift seamlessly to wherever your specific sweet spot is. Different parts of your program can even use different spots. In a game engine, you could have the audio and rendering parts as non-GC real-time code, while the game logic is easy high-level script-like.
We are very used to a scripting language plus compiled language combo these days but is the separation a good one?
http://michaelrbernste.in/2013/06/03/real-time-garbage-colle...
The trick is not loading the GC too much, neither in terms of allocations/second nor bytes/second (for multimedia it means recycling buffers as opposed to creating/destroying), also having enough RAM so you don’t need to use 80% of installed memory.
Anti-GC hate seems to always come from religious objection or having had back luck not understanding how to actually use the tools at their disposal.
One thing that having been an Oberon user teached me, was that having a GC wasn't a show stopper for systems programming.
Ironically C++ has has GC support for more than 20 years now.
Managed C++ and C++/CLI on .NET, C++/CX on UWP, Unreal C++, and the GC API introduced in C++11.
So it seems to be one of those things that you only learn to enjoy after experiencing it personally.
You'd be surprised. At first our D audio products had GC enabled, and that created very little problems. When we got rid of the D GC for other reasons (macOS + druntime portability in shared library), we found that we only gain in memory usage. The GC was already "tamed" to happen outside real time threads. This is described in: https://www.auburnsounds.com/blog/2016-11-10_Running-D-witho...
The conclusion:
> Long story short, we brute-forced our way into having fully @nogc programs, with the runtime left uninitialized.
> As expected this fixed macOS Sierra compatibility. As a bonus Panagement and Graillon are now using 2x less memory, which is nice, but hardly life-changing.
> We found no magical speed enhancement. Speed-wise nothing changed. Not registering threads in callbacks did not bring any meaningful gain. GC pauses were already never happening so disabling the GC did not help.
> In conclusion, it is still our opinion that outside niche requirements, there isn't enough reasons to depart from the D runtime and its GC.
And indeed now we dearly miss the GC...
For sure you wouldn't allocate in tight loops. But the portion of a program that can accomodate a GC is very much larger than is commonly told on the internet.
As for video, it is way less sensitive to scheduler pauses than audio. Video systems are full of allocations (often of commited virtual memory) because throughput is often more important than latency there.
golang's GC isn't advanced either.
Although most of the benchmarks I've seen are at lease 2 years old. It would be nice to see some updated benchmarks that also compare against the Shenandoah and ZGC garbage collectors for the JVM.
That's how you get from zero to heavy usage in companies like Uber, Twitter, Cloudflare, BBC, Basecamp, Canonical etc... in less than a decade.
Not to mention technology change always generate friction. You just can't please everyone.
Hype driven development is a thing.
Unless technology X is irrelevantant.
But real-world applications performance needs fine tuned libraries that scales and this is where Java destroy both go and c#.
I ran several benchmarks locally on a CPU that's a few years old where the benchmarks site shows golang being faster than Java, without changing the code, and I got the opposite result (Java was faster). Especially the longer the program ran. For example, the site shows that golang is faster in the spectral norm benchmark. Running it locally with a larger input parameter:
golang:
time ./test 30000
1.274224153
18.81 real 70.19 user 0.38 sys
Java: time java spectralnorm1 30000
1.274224153
16.18 real 105.95 user 0.45 sys
Or with the nbody benchmark:golang:
time ./nbody 60000000
-0.169075164
-0.169012474
6.09 real 6.04 user 0.02 sys
Java: time java nbody 60000000
-0.169075164
-0.169012474
6.04 real 5.94 user 0.06 sysThings should get more interesting once Java gets green threads, which would make it easier to implement high performance concurrent servers without needing to drop down to event driven code unless for specific needs. That, and with value types, should push the performance bar forward.
- https://blog.plan99.net/modern-garbage-collection-911ef4f8bd...
- https://blog.plan99.net/modern-garbage-collection-part-2-1c8...
The main takeaway is that saying that Go is the leading GC is just a (somewhat dishonest) PR move, and Go's team made a pretty good GC given there project constraints, even of it is not at the state of the art at the moment.
You know when you end your article with "Overall, it looks to me like the Java guys are winning the low latency game." when none of those GC are actually production ready ... Go GC low latency has been stable and used for some time now.
Out of the box Go GC is very good and doesn't need all the memory or the tunning from G1. ( I spend years tunning GC for Java application it's a nightmare )
And isn't Shenandoah included by default in OpenJDK 12+?
Oracle chooses to build with only ZGC enabled.
I would not be surprised if the difference in amount of "garbage"—as measured in either bytes or object count/mark time—were a lot smaller than people think.
So does Go. Otherwise it wouldn't be anywhere as popular specially with regards to server-side usage by giants of the industry.
Java GC don't need allocation tricks of several GBs, like Twich was forced to do.
It is not heap size that matters, but how often old objects are mutated. Basically, if you have 1TB of immutable objects, you are lucky, but if you constantly modify all the heap, then you will have a lot of headache.
GC authors continuously mislead on this issue for many years (they promised the same with multi gigabyte heaps but with G1 several years ago).