メモリを無駄にしない
わかったこと
方式を決める前に、まず計測しました。17 台の VM、44 GB のゲストメモリを持つホストで 1 日動かしたあと、ゲストメモリの 49% がゼロページで、35% は 2 MiB 単位でまるごとゼロでした。カーネルは解放したページをゼロクリアしますし、VM のメモリの多くは起動後一度も触られません。
ゼロのチャンクには保存すべき内容がありません。圧縮もスワップも、ゲスト内のドライバーも不要です。返すときは、新しくゼロクリアしたチャンクを渡せば済みます。
しくみ
- 低優先度のスレッドが 5 分ごとに、ゲストメモリを 2 MiB のチャンク単位でスキャンします。2 回続けてゼロだったチャンクは、ゲストからマッピングを外します。
- ゲストがそのチャンクに触れると、すぐにマッピングし直します。
- 回収したチャンクは、ホストの ZFS プールの L2ARC キャッシュデバイスになります。ゲストがチャンクを必要とすると、ホストはそのチャンクへのキャッシュ I/O を待ち、ゼロクリアして(約 0.1 ms)マッピングし直します。ZFS は L2ARC からの読み取りをすべてチェックサムで検証するため、チャンクが取り戻されても、ディスクからの読み取りが 1 回増えるだけです。
メモリは引き続きその VM のものです。ほかの VM には貸し出さないのでオーバーコミットはなく、メモリを返せなくなる瞬間もありません。
計測結果
- 開発用ホストで 7 時間:14.9 GB、ゲストメモリの 34% を回収。回収したチャンクのうち、返却を求められたのは約 5%。
- 実機での正しさの検証:ゲストがゼロとランダムなデータを書き込み、2 回のスキャンを待ってから、ホストの再起動をはさんで読み戻しました。すべてのバイトが一致しました。
- ARC 4 GB のホストでのランダム読み取りベンチマーク:貸し出しキャッシュなしで 10.7k IOPS、6 GB 貸し出した状態で 16.7k IOPS。
制限事項
- オーバーコミットはしません。回収したメモリをさらに多くの VM に使うかどうかは、返却を求められる頻度について数週間分の実データが集まってから判断します。
- パススルーデバイスを持つ VM は対象外です。デバイスがメモリに直接書き込むためです。
- VM のディスクが高速な NVMe 上にあり、ARC がすでに大半の読み取りをまかなっている場合、効果は小さくなります。ハードディスクのプール向けの機能です。パススルーしたコントローラーの先にあるディスクは、ホストのキャッシュを通りません。
- ゲストが読み取るだけのチャンクは、回収する代わりに 1 つのゼロページを共有させることもできますが、まだ実装していません。
- 設定はインストール済みのシステムで調整できますが、そのための Web ページはまだありません。