Improving Firefox stability with this one weird trick

https://hacks.mozilla.org/2022/11/improving-firefox-stability-with-this-one-weird-trick/

私が所有した最初のコンピューターには128KiBのRAMが搭載されていましたが、15年前のマシンでさえ4GiBのメモリが搭載されていることが多かったことを考えると、今日でもアプリケーションがメモリ不足になる可能性があるという考えに悩まされている。それでもFirefoxの場合、これはユーザーが経験する不安定性に関する最たる原因の1つであり、メモリ不足はWindowsでのクラッシュの最大の原因である。

そのため、Mozilla では、Firefox のメモリ消費量を削減し、変更を注意深く監視するために多大なリソースを費やしている。WindowsプラットフォームはmacOSやLinuxよりもメモリ不足になる可能性が高いため、FirefoxはWindowsプラットフォームに追加の労力が費やさせられている。しかし、メモリ消費量を削減するこれらの取り組みのどれも、Firefox 105 で展開したクールなトリックほどの影響はない。

しかしその前に、Windowsで実行されているアプリケーションが他のオペレーティングシステムと比較してメモリ不足になりやすい理由を理解するには、Windowsがメモリを取り扱う方法を理解することが重要です。

最近のすべてのオペレーティング システムでは、アプリケーションがアドレス空間のチャンクを割り当てることができる。 最初は、これらのチャンクは、データが格納されていない限り、物理メモリに支えられていないアドレス範囲のみを表す。 アプリケーションが予約済みのアドレス空間のビットを使用し始めると、OS はそれをバックアップするために物理メモリのチャンクを専用に割り当て、必要に応じて既存のデータをスワップアウトする可能性がある。 Linux と macOS の両方がこのように機能し、Windows も同様ですが、他の OS と比較して追加の手順が必要です。

コミット スペースと呼ばれるこのリソースは、アプリケーションのハード リミットです。 制限に達すると、メモリの割り当てが失敗し始めます。 オペレーティング システムの解説では、これは Windows がアプリケーションによるメモリのオーバーコミットを許可しないことを意味する。

Windowsシステムの興味深い点の 1 つは、アプリケーションが使用しないメモリをコミットできることです。コミットされた量は、対応する領域にデータが格納されておらず、コミットされた領域をバックアップするために物理メモリが使用されていない場合でも、制限に対してカウントされます。メモリ不足のクラッシュの分析を開始したとき、多くのユーザーがまだ物理メモリを十分に利用できることを発見した (場合によっては数ギガバイト)、その代わりにコミット スペースが不足していた。

なぜそれが起こったているのか実際にはわかりませんが、いくつかの経験に基づいて推測を行いました: Firefox では使用するすべてのメモリを追跡し、直接コミットしたすべてのメモリを説明できる。

ただし、Windows システム ライブラリ、特にグラフィックス ドライバーを制御することはできません。私たちが気づいたことの 1 つは、グラフィックス ドライバーがメモリをコミットして、システム メモリにテクスチャ用のスペースを確保することです。これにより、十分なテクスチャがない場合に GPU メモリからテクスチャをスワップし、代わりにシステム メモリに保持することができます。十分な RAM が利用できない場合に、通常のメモリをディスクにスワップ アウトする方法と同様のメカニズムになる。実際には、これはめったに起こりませんが、これらの領域は依然として制限に対してカウントされる。

この問題を直接修正する方法はありませんでしたが、まだ切り札がありました。Windows でアプリケーションがメモリ不足になった場合、OS によって完全に強制終了されるわけではありません。その割り当ては単に失敗し、それ自体で何をするかを決定できる。

場合によっては、Firefox が失敗した割り当てを処理できるが、ほとんどの場合、エラーを処理する適切で安全な方法はなく、制御された方法でクラッシュする必要がある。しかし、代わりにこの状況から回復できるとしたら?スワップ ファイルがほぼいっぱいになると、Windows は自動的にスワップ ファイルのサイズを変更し、使用可能なコミット スペースの量を増やす。もしかすると、これを有利に利用できるのではないだろうか?

この質問に対する答えは「Yes」であることがわかった。そのため、Firefox をクラッシュさせるのではなく、少し待ってから、失敗したメモリ割り当てを再試行するように調整した。これにより、ブラウザがほんの一瞬スタックする可能性があるため、多少のジャンクが発生するが、クラッシュするよりははるかに優れている.

これには別の見方もある。Firefox は複数のプロセスで構成されており、メインのプロセス以外はすべて失われても生き残ることができる。メイン プロセスのクラッシュを遅らせると、メモリが不足している場合に別のプロセスが停止する可能性がある。たとえば、メモリ消費量が暴走した Web ページを取り除くことによってメモリを解放することは、これによって実行を再開できるため、良い対策です。

コンテンツ プロセスが停止した場合、それが GPU プロセスである場合は再読み込みする必要があり、再起動中にブラウザが一時的に点滅する。いずれにせよ、結果は完全なブラウザ クラッシュよりも混乱を招くものではない。その前に Android 版 Firefox と Firefox OS で同様のトリックを使用し、両方のプラットフォームでうまく機能した。

この小さなトリックは Firefox 105 で出荷され、Windows での Firefox の安定性に大きな影響を与えた。以下のグラフは、アクティブな使用時間ごとにユーザーが経験したメモリ不足のブラウザー クラッシュの数を示す。
https://hacks.mozilla.org/files/2022/11/unnamed-3.png

クラッシュが 70% を超えて減少していることがわかる。これは、最も楽観的な予測をはるかに上回っている。

まだ終わりではありません! メイン プロセスを停止することで、タブ クラッシュの増加がわずかに抑えられた。これは、ブラウザー全体のクラッシュほど煩わしくはありませんが、ユーザーにとって不快なものでもある。そのため、タブ クラッシュも削減している。

最後に大事なことを言い忘れましたが、コミットスペースが不足している場合と物理メモリが不足している場合に異なる対応をすることで、メモリ不足のシナリオでの Firefox の動作を改善したいと考えている。これにより、スワップが減り、Firefox のフットプリントを縮小することは、他のアプリケーションのための余地となる。

この「トリック」を実装し、その影響を注意深く監視し、前述の改善に取り組んでいる同僚の Raymond Kraesig に特に感謝します。