Live data from Hacker News

Watching Go's new garbage collector move through the heap

theconsensus.dev

31–40 of 48 posts

Re: Watching Go's new garbage collector move through the heap

#31
post #23
post #6

Earlier quoted context omitted.

It's because of what's in the second paragraph, which I will paste here for convenience: "Taking a step back, Go manages memory by allocating objects of the same size class (an object’s size is rounded up to the nearest size class) within a contiguous chunk (or span in Go terminology) of one or more 8KiB pages. Size-segregated allocation is common in some malloc implementations (like tcmalloc, which Go’s allocator de…

> You can't get the inability to allocate some large object because there's a spray of small objects in its way ... The large objects live in their own space Assume for the sake of argument that the large object space is for objects >=1MB. Allocate lots of 1MB objects then free every other one (by address). Unless you're willing to let the large object space grow without bounds....

Large objects (≥ 32 KiB) does not use these categorized arenas, they instead allocate an integer number of 8KiB pages from a heap.

Re: Watching Go's new garbage collector move through the heap

#32
post #28
post #21

Earlier quoted context omitted.

Can't say I totally agree with the claim that GC is a dealbreaker for games. There are trade-offs either way and games typically need to do things a bit differently to achieve high performance anyway. It is, however, a strong benefit of Godot over Unity because Unity is still stuck with the worst possible GC (Boehm) for the foreseeable future.

> Unity is still stuck with the worst possible GC (Boehm) for the foreseeable future. How are we measuring "worst possible" here? Unity's GC is unique in that it has an incremental marking phase. The most important thing in a unity application is frame latency, not raw GC throughput. If you are generating so much garbage every frame that the incremental collector falls behind, that's probably on you.

> Unity's GC is unique in that it has an incremental marking phase.

Does ZGC not also have an incremental marking phase?

Re: Watching Go's new garbage collector move through the heap

#33

Tangential but this makes me think of a video about C# GC, and the developer switching to Swift to avoid it, in which the dev says they estimate the development of a pause-less GC to be 5B$ R&D away, does that ring the bell to anyone?

According to Cliff Click, compilers and JVM + some other systems programming guy, Azul has a JVM with microseconds pause times at very large heap sizes (10s, 100s of GB?) and allocation rates. That is "pauseless" for gaming purposes.

Re: Watching Go's new garbage collector move through the heap

#34
post #24
post #23

Earlier quoted context omitted.

> You can't get the inability to allocate some large object because there's a spray of small objects in its way ... The large objects live in their own space Assume for the sake of argument that the large object space is for objects >=1MB. Allocate lots of 1MB objects then free every other one (by address). Unless you're willing to let the large object space grow without bounds....

I haven’t read the article, but for allocations that large, chances are they get allocated as entire memory pages and the garbage collector returns that memory to the OS. Also, even if it doesn’t, in a 64-bit address space it takes lots of 1MB objects to make that cause problems (there’s room for over 10¹⁶ of such objects)

Correction: over 10¹³. Still a lot.

Re: Watching Go's new garbage collector move through the heap

#35
post #28

Earlier quoted context omitted.

> Unity is still stuck with the worst possible GC (Boehm) for the foreseeable future. How are we measuring "worst possible" here? Unity's GC is unique in that it has an incremental marking phase. The most important thing in a unity application is frame latency, not raw GC throughput. If you are generating so much garbage every frame that the incremental collector falls behind, that's probably on you.

> Unity's GC is unique in that it has an incremental marking phase. Does ZGC not also have an incremental marking phase?

Also, the default collector, G1, introduced more than 15 years ago. Most JVM GCs are concurrent, too.

Re: Watching Go's new garbage collector move through the heap

#36
post #34
post #24

Earlier quoted context omitted.

I haven’t read the article, but for allocations that large, chances are they get allocated as entire memory pages and the garbage collector returns that memory to the OS. Also, even if it doesn’t, in a 64-bit address space it takes lots of 1MB objects to make that cause problems (there’s room for over 10¹⁶ of such objects)

Correction: over 10¹³. Still a lot.

Sounds like a challenge.

Re: Watching Go's new garbage collector move through the heap

#37
Interesting and its noteworthy to observe that the new GC actually increases the rate of L3 misses slightly. For reference, L1 misses are quite fast, and often free since the CPU can cover up the empty slots with useful work, however L3 misses require a read from RAM which is an eternity in CPU cycles.

My theory is that Go programs cover up the wait for L3 via SMT (which is still kinda common on server CPUs) and schedule work from another hardware thread.

Such a technique might be less usable in less-threaded languages, or non-SMT CPUs and the new GC might end up being slower.

Re: Watching Go's new garbage collector move through the heap

#38
post #28
post #21

Earlier quoted context omitted.

Can't say I totally agree with the claim that GC is a dealbreaker for games. There are trade-offs either way and games typically need to do things a bit differently to achieve high performance anyway. It is, however, a strong benefit of Godot over Unity because Unity is still stuck with the worst possible GC (Boehm) for the foreseeable future.

> Unity is still stuck with the worst possible GC (Boehm) for the foreseeable future. How are we measuring "worst possible" here? Unity's GC is unique in that it has an incremental marking phase. The most important thing in a unity application is frame latency, not raw GC throughput. If you are generating so much garbage every frame that the incremental collector falls behind, that's probably on you.

A Jurassic GC introduced in Mono, that due to Unity not wanting to pay Xamarin for updates, meant it was mostly frozen in the days of Unity/Xamarin early collaboration.

Unity preferred to go down the route of HPC#, Burst compiler and IL2CPP, and is still maybe one to two years to fully migrate to modern .NET.

Meanwhile in Redmond, Mono is almost gone, with CoreCLR already in preview for mobile platforms,

https://devblogs.microsoft.com/dotnet/dotnet-maui-moves-to-c...

Capcom's RE engine also uses their own fork CoreCLR, customised for consoles, Devil May Cry for PS 5 uses it.

Re: Watching Go's new garbage collector move through the heap

#39
post #23
post #6

Earlier quoted context omitted.

It's because of what's in the second paragraph, which I will paste here for convenience: "Taking a step back, Go manages memory by allocating objects of the same size class (an object’s size is rounded up to the nearest size class) within a contiguous chunk (or span in Go terminology) of one or more 8KiB pages. Size-segregated allocation is common in some malloc implementations (like tcmalloc, which Go’s allocator de…

> You can't get the inability to allocate some large object because there's a spray of small objects in its way ... The large objects live in their own space Assume for the sake of argument that the large object space is for objects >=1MB. Allocate lots of 1MB objects then free every other one (by address). Unless you're willing to let the large object space grow without bounds....

There is a theorem that is often stated in operating system courses as "For any possible allocation algorithm, there exist streams of allocation and deallocation requests that defeat the allocator and force it into severe fragmentation.". You can ask your friendly local AI about "Bounds for Some Functions Concerning Dynamic Storage Allocation" by J. M. Robson in the July 1974 Journal of the ACM and some various follow-up papers. For any non-compacting memory management algorithm, including traditional malloc/free, there will always be a way of defeating it and forcing it to fragment.

However, consider that Go has been in production for 14 years now, and one of its bread-and-butter applications is network servers, which will collectively exercise quite a bit of the memory allocation pattern space, including some pathological aspects of it. You should expect to need to do better than that to really throw it for a loop.

While the theorem proves some such sequence exists, there's no guarantee that the sequences will be easy to describe in some sort of English sentence.

Post reply on HN