
On 01/03/2010 17:16, Sebastian Sylvan wrote:
On Sun, Feb 28, 2010 at 5:20 AM, Luke Palmer
mailto:lrpalmer@gmail.com> wrote: I have seen some proposals around here for SoC projects and other things to try to improve the latency of GHC's garbage collector. I'm currently developing a game in Haskell, and even 100ms pauses are unacceptable for a real-time game. I'm calling out to people who have seen or made such proposals, because I would be willing to contribute funding and/or mentor a project that would contribute to this goal. Also any ideas for reducing this latency in other ways would be very appreciated.
Since we're talking games here (my profession), I'd point out that it would be cool to be able to supply "hints" to the GC about when might be a good time to do a GC (without unconditionally forcing it), games in particular have some pretty specific properties that may be exploitable.
Presumably a non-trivial portion of the objects copied from the nursery/G0 are actually short-lived objects that just happened to have their short life-span overlap with the collection. So really, copying them to the next generation is a "mistake" in some sense.
There's a technique we use, that mitigates the effect of this to some extent, called "aging". The idea is that an object is only promoted if it survives at least N GCs in the young generation. Typically N=2 is a good value, so an object that is allocated just before a minor GC will be copied, but probably not promoted unless it survives all the way to the next GC. You can also use fractional values of N and in fact you should measure N in terms of bytes allocated rather than GCs. In GHC 6.12.1 you can tune the amount of aging with +RTS -T<n>, but I removed the option in 6.14 in order to make the GC implementation simpler, we now have a fixed aging -T2 aging policy. In practice other values were very rarely any better, in fact.
For games, though, we have a very good point that occurs regularly where we know that all/most short-lived objects will no longer be referenced - at the start of a fresh frame.
System.Mem.performGC is your friend, but if you're unlucky it might do a major GC and then you'll get more pause than you bargained for. Cheers, Simon