Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> there are tons of new, modern GC implementations that have no pauses

There are no GC implementations that have no pauses. You couldn't make one without having prohibitively punitive barriers on at least one of reads and writes.



There are no CPUs that have no pauses; who knows, you may have to wait a microsecond for that cache line to come in from RAM.

There are no operating systems that have no pauses; if you don't want to share the CPU, you're going to have to take responsibility for the whole thing yourself. Most people are not even using RTOS.

There are no reference counting implementations that have no pauses. Good luck crawling that object graph. Most people are not even using deferred forms of reference counting.

As far as I know, there is one malloc implementation which runs in constant time. No one uses it.

There are tracing GCs whose pause times are bounded to 1ms. That is enough for soft-real-time video and audio (which is what matters to video games). In general, you are not going to get a completely predictable environment unless you pick up an in-order CPU with no cache and write all your code in assembly.


I think the more accurate / useful statement is, there's no GC with bounded pause times that's also guaranteed to free memory fast enough you don't run out even though you shouldn't. In other words, GC can never fully replace thinking about your allocation patterns.

(I suspect this is obvious to a lot of programmers, but especially in working with Java programmers who just skim JVM release notes and then repeat "pauseless", it's also not obvious to many too.)


> GC can never fully replace thinking about your allocation patterns

Of course not! Nothing can. But—two things:

1. Per Knuth on premature optimization, 97% of your code should not care about such things. For those parts of your code that do need to effect their own allocation strategies, they can generally do so as well in a GCed language as another. Tracing GC forces minimal cognitive overhead on the remaining 97%, and allows it to interoperate smoothly with the 3%.

2. Tracing GC has better performance characteristics than other automatic memory management policies, in a few important respects. Compacting adds locality; bumping gives very fast allocation; copying gives very fast deallocation of deep graphs in the nursery.


The problem is that garbage collection does impact that 3 %... since unless you’re using naive gc garbage collection limits your ability to not manage memory automatically. In general reference counting is more tolerant of mixing reced and non ref counted code. This hurts more since gc gives performance in the part of the code where performance doesn’t matter, while hurting you where performance does! And yes this is alleviated somewhat by memory pools, but not entirely.


> Of course not!

Like I said - "of course" to me, and apparently you, and probably anyone who has worked with multiple GCs and unmanaged languages over many years - but that's not most programmers. The vast majority of Java developers I interview, up to those with 5-6y experience, have no clue how their idioms affect allocations.

> Per Knuth on premature optimization, 97% of your code should not care about such things.

No, this is the classic misstatement of Knuth. 97% of the time, I shouldn't worry about such things. But 100% of my program still might be affected by a design needed to reduce GC pressure, if that means switching core data structures to pools or SoA or something.


Right, but if you're allocating way too much, no lifetime management model will save you.

As a game dev I still will take a modern GC over refcounting or manual lifetime management any day. There are scenarios where you simply don't want to put up with the GC's interference, but those are rare - and modern stacks like .NET let you do manual memory management in cases where you are confident it's what you want to do. For the vast majority of the code I write, GC is the right approach - the best-case performance is good and the worst-case scenario is bad performance instead of crashes. The tooling is out there for me to do allocation and lifetime profiling and that's usually sufficient to find all the hotspots causing GC pressure and optimize them out without having to write any unsafe code.

The cost of having a GC walk a huge heap is a pain, though. I have had to go out of my way to ensure that large buffers don't have GC references in them so that the GC isn't stuck scanning hundreds of megabytes worth of static data. Similar to what I said above though, the same problem would occur if those datastructures had a smart pointer in them :/


This is a meaningless assertion, if you insist on going that far we have to discuss whether OS context switches cause your process to pause or whether the allocator you're using causes page faults. When people say 'gc implementations that have no pauses' they mean no stop-the-world, which IS an achievable thing in production collectors in many cases.




Consider applying for YC's Winter 2027 batch! Applications are open till November 2.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: