FirefoxのGCまわり

なんとなくちょっとだけ読んでみた。Firefoxにおいて、JSが使うメモリはコンパートメント、チャンク、アリーナの順に分解される。コンパートメントがどうも一番大きな区切りらしく、通常はこの単位でGCが呼ばれる。コンパートメントはホスト単位で確保されるらしい。チャンクは特に特徴のない塊で、アリーナは型毎に作られる。

GCはFull GCとコンパートメントGCがあり、後者ではコンパートメント単位でGCが行われる。TriggerGCが呼ばれるとFull GCが実行され、TriggerCompartmentGCが呼ばれるとCompartment GCが実行される。TriggerGCを呼んでいるところはgrepした限りではAllocateArenaとTriggerCompartmentGCの2つだけで、AllocateArenaはPickChunkに失敗したときにだけ呼ぶ。TriggerCompartmentGC内では以下のような条件で呼び出している。

    if (rt->gcBytes > 8192 && rt->gcBytes >= 3 * (rt->gcTriggerBytes / 2)) {
        /* If we're using significantly more than our quota, do a full GC. */
        TriggerGC(rt);
        return;
    }

つまり、フルGCはメモリが確保できない時か、あらかじめ設定された以上の容量を使っていた場合に行われる。

一方、TriggerCompartmentGCはChunk::allocateArenaから呼ばれる。この際の条件は以下のようになっている。

    if (comp->gcBytes >= comp->gcTriggerBytes)
        TriggerCompartmentGC(comp);

gcBytesはArenaをallocateした分だけ増えるので、これもやはりあらかじめ設定されたいた以上の容量のメモリを使っていた場合にGCが呼ばれる、という条件である。

特にまとめとかはないが、GCが行われるのはメモリをあらたにallocateしようとした時である、と言えそうだ。