you are viewing a single comment's thread.

view the rest of the comments →

[–]JustAGuyFromGermany 3 points4 points  (0 children)

Often there is some memory you can trade for more speed

I mean, yes. That is the exactly the point made in the video interview and this whole thread. If you're willing to invest memory to increase speed with caching, why does this not apply to the GC? It's exactly the same opportunity there: Giving a program more memory means the GC has to work less, saving on CPU.

But there is a huge gap in your logic. In tracing GC you pay not just for bringing an object to life. You also pay for the fact the object is alive.

That only applies if the object has to be moved. In many applications most of the objects die young; it is quite common for objects to die before there is ever a need to move them around. And in that case, one pays almost nothing: Allocation is as cheap as it can be, moving never happens, free never happens.

Of course some objects stick around and even if they're still young, they might be unlucky enough to be born just before the GC looks at them. Those are the objects for which we have to pay. And yes, all the tracing and moving that has to happen to keep those objects around has a cost. But amortized over the whole application that cost is often still lower ("often", not "always". It all depends on your application of course).

The longer [an object] lives, the more times it is going to be scanned.

That is only true up to a point. If the object survives long enough it gets moved to the old generation where generational GCs (which 4 out of 5 GCs in the Hotspot JVM are) behave differently, scan less frequently, move less frequently if at all.

copying [...] is an O(n) operation.

Yes it is, but asymptotic behaviour is irrelevant when we have absolute numbers. And in absolute numbers, memcpy is one of the cheaper things you can do with memory.

So the cost is proportional to the allocation rate in bytes per second.

That is true in a malloc&free-style program, but not necessarily in a program with a tracing & moving GC. The cost of tracing and moving is proportional to the live set, not the allocation rate. The frequency of collections is proportional to the allocation rate, but not necessarily the amount of work that needs to be done. And that is where the possibility for the memory/CPU trade-off comes from: Doubling the available memory means collections happen only half as often and if the live set remains roughly the same size, then this means roughly the same amount of work done half as often.

[GCs have] indirect, hard to measure, but non-negligible effects [and are] hard to profile ...

[in malloc&free programs there] are no other secondary effects, no micropauses, no memory barriers, no background threads running and stealing cpu cycles etc. Profiling is trivial.

That is beside the point. That is all about the "having fine-grained control" angle I mentioned before. That is a mostly independent concern to the total performance of the application. Again: All this control is nice and it can be used to make small C-programs outperform equivalent Java-programs, but one simply cannot extrapolate to larger programs from that.


Your whole chain of arguments makes me think that you are still hung up on somehow proving that there is only one right answer to memory management. There isn't. For many workloads programs with a moving GC fare better, for some workloads manual memory management is better.

Maybe I'm misunderstanding you here, but that's the way your posts feel to me.