Windowsでは、メモリ不足がFirefoxの最大のクラッシュ原因だった。しかし影響を受けたユーザーの多くは、数ギガバイトの物理RAMが空いていた。Windowsはアプリケーションがコミットできるメモリ量をRAMとスワップファイルサイズの合計に制限しており、Firefoxはその「コミット領域」を消費するすべてを制御できなかった。グラフィックスドライバーはテクスチャ用にめったに使われないメモリをコミットするが、それでも上限に計上される。Firefoxは長年にわたり自身のメモリ使用量を削減し、リグレッションを監視してきたが、どの取り組みも最終的な工夫ほどクラッシュ率を動かさなかった。

満たせない割り当てに対する従来の対応は諦めることだった。ほとんどの失敗経路には続行する合理的な方法がないため、ブラウザは制御された方法でクラッシュした。これはコミット領域の上限を固定とみなしていたが、Windowsではそうではない。オペレーティングシステムはスワップファイルがほぼ満杯になると自動的に拡大し、アプリケーションがコミットできるメモリ量を増やす。

Mozillaの取った策は、割り当てが失敗したときにメインプロセスを短時間待機させてから再試行し、Windowsにページファイルを拡大する時間を与えることだった。この停止には別の利点もある。Firefoxは複数のプロセスとして動作し、メインプロセス以外のいずれかを失っても生き残れるため、遅延の間に暴走したメモリを持つコンテンツプロセスやGPUプロセスが先に終了し、ブラウザが再開する余地を解放する傾向がある。ウェブページを失うか一瞬のちらつきを見るほうが、ブラウザ全体のクラッシュよりましである。

この工夫はFirefox 105で出荷され、アクティブ使用時間あたりのメモリ不足によるブラウザクラッシュを70%以上削減した。これはMozillaの最も楽観的な予測をはるかに超えていた。チームは同じアプローチをFirefox for AndroidとFirefox OSで成功裏に使っており、メモリ逼迫下でのタブクラッシュの小幅な増加が次に削減しようと取り組んだ課題だった。

Windowsでは失敗した割り当ては致命的である必要はない。OSは要求に応じてページファイルを拡大するため、待機して再試行することでメモリ不足クラッシュを短い停止に変えられる。

Windowsは割り当てが失敗したアプリケーションを強制終了しない。呼び出しはエラーを返すため、プロセスは終了する代わりに待機して再試行することを選べる。

コミット領域の上限は拡張可能である。Windowsはほぼ満杯になるとスワップファイルを自動拡大し、短い一時停止がその時間を与える。

Firefoxのマルチプロセス設計により、メインプロセスを停止させると再読み込み可能なコンテンツプロセスやGPUプロセスが先に終了してメモリを解放し、ブラウザ全体を保護できる。

この変更はメモリ使用量ではなく失敗処理を変えた。だからこそ一つの小さな修正が長年のフットプリント削減を上回ったのである。

プラットフォームがリソースを要求に応じて拡張できる場合、失敗時にクラッシュするのではなく一時停止する。マルチプロセスアプリでは、再読み込み可能なサブプロセスにまず損害を吸収させる。

Firefox 105は2022年9月に待機と再試行の動作を出荷し、テレメトリはアクティブ使用時間あたりのメモリ不足によるブラウザクラッシュが70%以上減少したことを示した。これは「最も楽観的な予測をはるかに超えていた」。この停止はタブクラッシュの小幅な増加を引き起こし、チームはその後その削減に取り組んだ。またMozillaはコミット領域の不足と物理メモリの不足を区別し始め、Firefoxが異なる対応をしてスワッピングを減らせるようにした。エンジニアのRaymond Kraesigがこの工夫を実装し、その影響を監視した。同じ手法はすでにFirefox for AndroidとFirefox OSで成功していた。

出典をたどる

出典

  1. Improving Firefox stability with this one weird trick Mozilla Hacks · hacks.mozilla.org ·
  2. Hacker News discussion: Improving Firefox stability with this one weird trick Hacker News · news.ycombinator.com ·