jemalloc on Windows - Firefox3 のメモリ使用量

面白いです.

jemalloc

firefox-3.0b4-source のソースを取ってきて,mozilla\memory\jemalloc\jemalloc.c を眺めてみるとよさげ.
軽く眺めてみたメモ.

気になった点

Stuart Parmenter さんの書いていることで気になったのはこの辺.

メモリ使用量の測定

この節の内容は少し技術的だ. 読むのを飛ばして構わない. 短くまとめるとこうなる. Windows Vista (コミットサイズ) と Linux (RSS) は至って正確なメモリ計測の数値を出す. 一方の Windows XPMacOS X は正確でない.

読者が Windows Visa を使っているなら, タスクマネージャのコミットサイズを見ているといい. その数字はとても正確なものだ. XP でメモリ使用量をみると, その数字はあまり良いものじゃない. 理由はこうだ: Microsoft は "private bytes" の意味を XP から Vista で(良い方に) 変更した.

XP ではこの数字がアプリケーションの予約(reserve)した仮想記憶サイズになる. 性能上の理由で実際に使うより多くのメモリを予約することはよくある. アプリケーションはオペレーティングシステムに, 予約した領域の一部は使わず, 仮想空間を物理空間に戻さない (訳注:よくわからず) と伝えることができる. Vista では, private bytes はコミットサイズをあらわす. これはアプリケーションが実際によく使うメモリの量だけを数えたものだ. 仮想記憶のサイズはコミットサイズより大きいか同じくらいだから, XP のメモリ使用量は Vista より多く見える. 実際には同じ量しか使わなくてもね.

Mac では, Activity Monitor が実際に使っている以上のメモリを使っているような表示をする. Mac OS XWindows XP と似たような, しかし異なる問題を抱えている. 徹底的なテストをしたあと Apple の従業員に確認したところ, アロケータがアドレスの範囲を予約したまま未使用のページをシステムに戻す方法はないことがわかった. (unmap して remap することもできるが, これには競合条件があり, うまくない.) こうした機能を持つと主張する API はある. (madvise() と msync()), しかしこれらは実際のところ何もしない. マップされたが書き込まれていないページはメモリの統計対象にならないようだ. しかし書き込むと, unmap するまで場所をとるようになる. 普通は大量の未書き込みページをマプしておくことはない. アプリケーションは空きページを再利用できるし, 実際するだろう. だから Firefox がメモリ使用量の最大値を記録したあと, それより多くのメモリをつかわないという状態を目にすることだろう.

Linux のメモリ使用量の報告はいたって良好だ. Linux は madvise() をサポートする. おかげで Linux では不要なページをシステムに教えることができる. だから常駐メモリサイズ(resident set size)はとても正確だ. RSS を測るには ps や top を使うことができる.

  • Linux の常駐メモリサイズに対応するものは,Windows ではワーキングセットなんじゃなかろうか.なんか初っ端から違うものを並べている気がする.
  • 「XP ではこの数字がアプリケーションの予約(reserve)した仮想記憶サイズになる. 」とあるけど,実際に試してみると "private bytes" は MEM_RESERVE のみの領域を含んでない.MEM_COMMIT してはじめて増加している.少なくとも手元の Windows XP SP2 (x86) で Stuart さんが言うような現象はみられない.
    • XP までの "private bytes" は,MEM_COMMIT されたサイズだけでなく,rebasing のせいで Copy on write された領域とかまで含んでいたのが問題とされたんじゃなかろうか.確保済みのスタック領域とかも含まれてそう.(追記) スタック領域で割り当て済みの領域も含まれるで正解っぽい.
    • Vista 以降は,純粋に MEM_COMMIT されたサイズのみの合計値になった.つまり,ややこしい理由で割り当てられているメモリが含まれなくなった,んだと思う.(追記) Vista で調べてみたけど,スタック領域で割り当て済みの領域も "private bytes" に含まれるっぽい.MEM_COMMIT で VirtualAlloc のみを想像すると間違いかも.
  • Windows でも MEM_RESET 後に VirtualUnlock や,MEM_DECOMMIT 直後の MEM_COMMIT などで不要なページ (内容保持の必要なくなったメモリページ) をシステムに教えることができる.