ページテーブルは仮想メモリシステムの基本的な構成要素であり、仮想アドレスを物理アドレスに変換します。ただし、特定のワークロードではそのメモリ消費が大きくなり、マッピングしている実際のデータに匹敵またはそれを上回ることがあります。 コアの問題は、ページテーブルがメモリを共有するプロセス数にどのようにスケールするかにあります。Fernando Simõesが説明しているように、複数のプロセスが同じ物理ページをマッピングする場合、各プロセスはそのページをマッピングするために独自のページテーブルエントリ(PTE)が必要となります。各PTEは通常8バイトを占め、標準的なデータページは4 KiB(4096バイト)です。したがって、計算は単純です:同じページをマッピングする512のプロセスは、512 × 8バイト = 4096バイトのPTEを必要とし、これはちょうど1つのデータページのサイズになります。つまり、512のプロセスがメモリを共有するとき、ページテーブルのオーバーヘッドは共有データそのもののサイズと等しくなります。 この関係は、広範なメモリ共有を含む実際のシナリオで問題となります。あるケースでは、Qi Zhengが、590 GiBの常駐セットサイズ(RSS)を持つプロセスが110 GiBのページテーブルを伴っていることを観測しました。理論上の最小値はPTEで約1.2 GiBであるべきでした。この乖離は、ワークロードがjemallocとtcmallocを使用し、munmap()ではなくmadvise(MADV_DONTNEED)を介してカーネルにメモリを返却していたために生じました。madvise(MADV_DONTNEED)は実際のデータページを解放しPTEをクリアしますが、ページテーブル構造自体を解放しないため、時間とともに空のページテーブルが蓄積します。 データベースワークロードでも同様の問題が報告されています。 この問題は単純な共有メモリシナリオにとどまりません。Windowsでは、Sopelがゾンビプロセスは実際のメモリを消費しないにもかかわらず、それぞれ少なくとも32 KiBのページテーブルを保持し続けることを指摘しています。極端なケースとして、AMD iGPUドライバのバグにより、終了したcmd.exeプロセスが100,000個残留し、約3.5 GiBがページテーブル構造に占有されました。 軽減策は存在しますが、トレードオフを伴います。その他に提案されている解決策として、プロセス間でページテーブルを共有できるmshareや、madvise(MADV_DONTNEED)が使用されたときにページテーブル構造を解放するカーネルの変更があります。後者のアプローチは、いくつかの改訂を経て2025年にLinuxカーネルにマージされました。 ページテーブルのメモリ消費を理解することは、特に共有メモリや多数のプロセスを含むメモリ集中的なアプリケーションを扱うシステム管理者や開発者にとって重要です。なぜなら、利用可能に見えるメモリが実際にはこれらしばしば見落とされがちなデータ構造によって消費されている可能性があるからです。