top | item 8948267

(no title)

joelgwebber | 11 years ago

Yes, sort of. Not generating a large amount of garbage can still give the runtime an opportunity to reduce the amount of work done per collection pass. A naïve heuristic for determining when to run GC will give you the typical "sawtooth" pattern, because you generate garbage until hitting a fixed ceiling threshold, collect it all, then wash, rinse, repeat. But a game that's not completely pegging the CPU will have some idle time that can be used for small collections, so limiting the amount of garbage produced on each frame should put an upper bound on the amount of work done during each frame.

When I was helping Rovio port Angry Birds to the web a few years ago, we ran into serious frame hitches that were being triggered by GC pauses in Chrome. Two things fixed this -- the first was fixing a bug that caused it to run a full mark/sweep far too aggressively; but the second was when V8 committed an incremental collector (not concurrent, just able to spread the work out more by being able to run a partial mark/sweep and resume it later). After that, the GC pauses disappeared into tiny ~N00µs pauses that never impacted the game.

discuss

order

hedgehog|11 years ago

Right now Go uses the naive heuristic you describe, there's no concurrent or incremental collection so no matter how long it takes to get to the GC it'll be a stop-the-world collection and potentially take a long time. I forgot to mention that besides reducing the amount of on-heap data you can also speed up collections in the current GC by lowering the GC threshold (SetGCPercent). This does come at the cost of collecting more often though so it's only really helpful if you're generating a lot of garbage on a relatively small heap. The impression I get is that for Angry Birds you would be fine with the 1.4 GC but Sim City might have some issues.

https://docs.google.com/document/d/16Y4IsnNRCN43Mx0NZc5YXZLo...

Go might eventually get a generational GC but my understanding is that that pretty much requires a copying GC and there are concerns with C interop (right now you can point to Go memory from C).

pcwalton|11 years ago

> Go might eventually get a generational GC but my understanding is that that pretty much requires a copying GC and there are concerns with C interop (right now you can point to Go memory from C).

It does. Also note that incremental GC in Go is going to have different performance characteristics than incremental GC in JavaScript, because of the fact that Go's GC has to be thread-safe.

joelgwebber|11 years ago

Indeed. I'm hopeful that the concurrent GC will get it to the point where it can do a lot better than that "10ms out of every 50" promise in 1.4. If not, then well, I guess we will have learned that Go isn't great for games after all.

/me crosses fingers.

agmcleod|11 years ago

> but the second was when V8 committed an incremental collector

Did the chrome developers have to fix v8 for that one?

joelgwebber|11 years ago

This was a fairly obscure bug lurking in the DOM/API bindings. They have to do a bunch of wacky stuff to deal with the interactions between the V8 GC and the ref-counted native API objects. In this case, the TypedArray wrapper objects were implemented in such a way that allocating them would often trigger a full mark/sweep (which also, IIUC, contained the logic necessary to free up reference cycles in native objects pinned by V8). My understanding is that all that stuff is much better now, and much less likely to lead to such pathological behavior.