News for hackers. Stuff that matters.
Re:GC Tuning Confessions of a Performance Engineer by pcwalton on Friday May 29, 2015 @01:52PM (#9626172)
I think the solution is to use the right memory management tool for the job. pron is right that GC can be helpful for concurrent data structures (where the non-GC approach, hazard pointers, is basically just a GC), for instance. GC is also great when your objects have truly dynamic lifetime, such as open files in Unix from the kernel's point of view. But GC for all data tends to be overkill when your goal is to maximize performance: a pure number-crunching workload like a triangle rasterizer has no need for GC, since the memory management is so trivial that it's better for the programmer to manually specify it (and, ideally, have the compiler check that) than for the program to spend cycles figuring it out at runtime. So, in my view, the best memory management discipline is a flexible one that allows the choice between automatic and manual memory management on a case-by-case basis.
Re:GC Tuning Confessions of a Performance Engineer by pron on Friday May 29, 2015 @06:27PM (#9627879)
I think we should look at the problem the other way around: it is manual memory management that is overkill because there are exactly four kinds of object memory scope:

* stack scope * transaction scope (for some definition of transaction -- it can be, say, a frame in a game, or a request in a web server) * arbitrary (database or any shared data structure) * permanent

For the stack scope, we have the stack. For the arbitrary scope, a GC is invaluable. For the permanent scope, it doesn't matter too much whether you have a GC or not (yes, vitalyd is going to mention traversals, but if the traversals are interesting, they point to objects in the arbitrary cost anyway). This leaves us the transaction cost. Now, I think it is far easier to manage a stack scope in a GCed environment than an arbitrary scope in a manual environment, and, in fact, some GCs, such as HotSpot's G1 should (yes, vitalyd, it doesn't always work) figure out the tranaction boundary automatically, but even if they don't, it's fairly easy to get that functionality with object pooling. However, to get the absolute best we shouldn't add a GC to a manually managed environment, but add arena collections to a GCed environment, which is exactly what RTSJ (realtime Java) does with scoped memory (making sure there are no references from potentially longer scopes into the arena).

To sum up, for the absolute best performance, a GCed environment + arenas has all you need. There is absolutely no need for a per-object malloc/free, and reference counting is neither here nor there (contention, cycles).

Re:GC Tuning Confessions of a Performance Engineer by pcwalton on Friday May 29, 2015 @06:33PM (#9627912)
> yes, vitalyd is going to mention traversals, but if the traversals are interesting, they point to objects in the arbitrary cost anyway

I'm going to mention this too. I don't understand what you mean by "they point to objects in the arbitrary cost anyway". The fact of the matter is that you have to trace all objects at some point.

> Now, I think it is far easier to manage a stack scope in a GCed environment than an arbitrary scope in a manual environment, and, in fact, some GCs, such as HotSpot's G1 should (yes, vitalyd, it doesn't always work) figure out the tranaction boundary automatically, but even if they don't, it's fairly easy to get that functionality with object pooling.

Object pooling is just a (limited, error-prone, poorly-performing) form of manual memory management.

> reference counting is neither here nor there (contention, cycles).

Contention isn't a problem if you don't touch the reference counts much. Cycles aren't a problem if you don't have cycles.

Re:GC Tuning Confessions of a Performance Engineer by pron on Saturday May 30, 2015 @01:47PM (#9630991)
> I'm going to mention this too.

What I mean is that either those refs are permanent -- in which case they won't be traced -- or arbitrary -- in which case it's really more of an "arbitrary" problem than a "permanent" one.

> Object pooling is just a (limited, error-prone, poorly-performing) form of manual memory management.

... And reference counting is just a (limited, error-prone, poorly-performing) form of garbage collection.

> Contention isn't a problem if you don't touch the reference counts much. Cycles aren't a problem if you don't have cycles.

But now you've added restrictions that are much more onerous than those of object-pools.

In any case, my main question is this: if absolute top performance is what you need, why not have a GC + arenas (like RTSJ) without ref counting/manual management? In my opinion, there's only one downside to that approach is RAM footprint. If that's your answer, then I agree (I think that that's pretty much the main reson not to use a GC).

Re:GC Tuning Confessions of a Performance Engineer by vitalyd on Friday May 29, 2015 @07:23PM (#9628140)
>I'm going to mention this too. I don't understand what you mean by "they point to objects in the arbitrary cost anyway". The fact of the matter is that you have to trace all objects at some point.

I think he means that if you have object references, then those references are interesting for the application itself, and not just for the GC tracer. However, I don't buy this statement simply because, even if you elect to store things as references rather than interior allocs, your app will only pointer chase the things it cares about, whereas the GC tracer may chase pointers that your app wouldn't otherwise.

@Ron:

The "arbitrary" scope better not be really arbitrary since even GCs are typically tuned for the generational hypothesis: your objects better be either short lived or long lived, anything in between is likely to degrade GC performance. In fact, if you like at some of the big data java solutions, once they reach a certain heap size, GC starts killing them, and they end up building their own semi-hybrid solution of moving stuff off-heap, and then managing that memory themselves (using the exact same block/slab/arena allocation techniques being downplayed here!).

For things like databases where object lifetime is in the hands of the user, arena/slab allocators work just fine. The additional advantage here is that you rarely need to destroy just a single object somewhere, typically it's an entire blob of related stuff. Arena destruction is more efficient here than GC because it's it inherently has more context than GC (the engineer wrote it, afterall). Is it more challenging/harder to implement than simply punting to the GC? Probably yes. But if you run afoul of GC's ergonomics and/or need to start tuning the finer points of GC behavior (i.e. see above comment about most of the big data java projects hitting this wall), the time spent there may end up exceeding arena impl costs.

Re:GC Tuning Confessions of a Performance Engineer by pron on Saturday May 30, 2015 @12:46AM (#9629015)
> I think he means that if you have object references, then those references are interesting for the application itself, and not just for the GC tracer.

What I mean is that either those refs are permanent -- in which case they won't be traced -- or arbitrary -- in which case it's really more of an "arbitrary" problem than a "permanent" one.

> The "arbitrary" scope better not be really arbitrary since even GCs are typically tuned for the generational hypothesis

By arbitrary I mean long-lived (old-gen) but not permanent. In short: database data.

> For things like databases where object lifetime is in the hands of the user, arena/slab allocators work just fine.

What you are saying is that you never truly have arbitrary-lifetime objects, and I strongly disagree with that.

> the time spent there may end up exceeding arena impl costs.

Even if you're right about arenas (which I don't agree with), you believe that a runtime designed to target the vast majority of server software should force developers to figure out lifetimes and that that may be beneficial to them? I mean, I even mentioned arena just to get that much closer to 100% performance. Even without them Java gets to at least 90%. Are you suggesting that the vast majority of projects in the world are interested in doing more work that is likely error prone just to get that 10% at best?

Re:GC Tuning Confessions of a Performance Engineer by Manishearth on Friday May 29, 2015 @02:17PM (#9626333)
+1. This is why I'm so excited about GC libs in Rust (and am working on a GC myself with @mystor). Rust has a nice undertone about choosing your costs and your guarantees, and if it got a good GC* people would have a really complete ecosystem for memory management.

*so, not the one I'm working on :P

Re:GC Tuning Confessions of a Performance Engineer by vitalyd on Friday May 29, 2015 @01:59PM (#9626233)
GC does help with ABA style concurrent problems, and it also simplifies the places where you simply don't care (slow/uncommon paths). But concurrent data structures are a special case, and likely, not always the best anyway since even though they scale much better than locks, with enough writers and cores, the cache coherence traffic is going to swamp the application.

I do agree with the flexibility comment. A hybrid environment where you can pick and choose the mem mgmt strategy (and, very important, not pay in perf for things you're not using) would be great.

Re:GC Tuning Confessions of a Performance Engineer by pron on Saturday May 30, 2015 @12:50AM (#9629034)
> GC does help with ABA style concurrent problems

I wasn't just referring to that. GC helps with pretty much any concurrent data structure, lock-free or not. For example, read-write locks don't scale too well (certainly no beyond the core count we're quickly coming up against on servers), and GC enables easy optimistic locking.

Re:GC Tuning Confessions of a Performance Engineer by Dewie3 on Wednesday June 03, 2015 @11:16AM (#9653172)
> I think the solution is to use the right memory management tool for the job.

That's like a generalization of my own argument. Generalized to the point where we are in the domain of truisms like "right tool for the job" (as opposed to what, the wrong tool for the job?).