Also the nature of pauses is different. A GC pauses everything. A malloc/free call only blocks the thread that called them. Threads that never allocate anything are never disturbed.
Also the nature of pauses is different. A GC pauses everything. A malloc/free call only blocks the thread that called them. Threads that never allocate anything are never disturbed.
Of course if you allocate arenas and reuse that cleverly you can beat any GC, but that’s far from obvious nowadays (e.g. I remember a reddit thread where naive Java beat naive Rust in some parsing to AST program (can’t find it currently). The reason was the speed of object allocation).
Here is a what I found:
"The ZGC design strives to deliver a max pause time of a few milliseconds with marginal throughput loss." [1]
"We now have an objective of 500 microseconds stop the world pause per GC cycle." [2]
Of course, those GCs have different tradeoffs in terms of max pause time, app throughput, memory fragmention/usage, etc.
[1] Deep Dive into ZGC: A Modern Garbage Collector in OpenJDK , September 2022, https://dl.acm.org/doi/fullHtml/10.1145/3538532
[2] Getting to Go: The Journey of Go's Garbage Collector, July 2018, https://go.dev/blog/ismmkeynote