Linux 7.3、メモリ管理に2つの高速化。ロック保持500ms超が2ms未満に

Linux 7.3のマージウィンドウで、メモリ管理サブシステムに2つのパフォーマンス改善が入った。圧縮メモリの解放処理で最大1.83倍、KSMの逆引きマップ走査でロック保持時間を100〜500分の1に短縮する。

Linux 7.3、メモリ管理に2つの高速化。ロック保持500ms超が2ms未満に

Linux 7.3のマージウィンドウで、メモリ管理サブシステムに2つのパフォーマンス改善が入った。圧縮メモリの解放処理で最大1.83倍、KSMの逆引きマップ走査でロック保持時間を100〜500分の1に短縮する。


501本のパッチ、概要の下書きにGemini

Linux 7.2が現地時間8月17日にリリースされ、7.3のマージウィンドウが開いた。翌18日、メモリ管理(MM)サブシステムのメンテナであるアンドリュー・モートン(Andrew Morton)氏がリーナス・トーバルズ(Linus Torvalds)氏に向けて、最初のプルリクエストを送った

今サイクルは活発だった。モートン氏がパッチ採用時に発行する"added-to-MM"(MM追加通知)メールは1,250通。前サイクルの920通から35%増えた。今回の第1弾だけで501本のパッチが含まれ、さらに約200本が翌週に控える。

モートン氏はプルリクエストの中で、パッチシリーズの概要文をGoogleのGeminiに下書きさせ、自分でレビュー・編集したと明かしている。カーネル開発にAIが浸透し始めているが、メジャーサブシステムのメンテナが「AIに書かせた」と公の場で書くのは、まだ珍しい光景だ。

レビュー状況も数字で示されている。501パッチ全体のレビュー率は70%、1パッチあたり平均1.66件。ただしDAMON(Data Access MONitor)関連のパッチを除くとレビュー率は90%に上がり、さらにセルフテストも除けば92%に達する。DAMONだけで145本ものパッチが入っており、レビューの手が追いついていない。

zsmalloc:圧縮メモリの解放が最大1.83倍に

501本の中で特に注目すべき改善が2つある。

1つ目はzsmalloc(圧縮RAMページ用のメモリアロケータ)におけるzs_free()のロック競合の削減だ。zsmallocはZswapやzRAMが圧縮したRAMページを格納するために使う。メモリが逼迫した状況でページを解放する際、zs_free()の内部でロックの競合が発生し、特にAndroid端末のLMK(Low Memory Killer)発動時や、サーバーでZswapを多用するワークロードで顕著だった。

Xiaomiのウェンチャオ・ハオ(Wenchao Hao)氏によるパッチシリーズは、64ビット環境においてzs_free()がプールレベルのロック(pool->lock)を取得せずにクラスインデックスを引けるよう設計を変更した。

ベンチマークでは、各プロセスが256MBのメモリ領域を個別にマッピング→書き込み→zRAMへのスワップアウト→並行アンマップ、という手順で測定されている。Raspberry Pi 4B(4コアARM Cortex-A72)では最大1.83倍、20コアIntel i7-12700(16並行プロセス)では最大1.4倍の高速化が確認された。

メモリ価格の高騰でサーバーのZswap/zRAM利用が広がっている現状を考えると、このロック競合の解消は地味ながら実利が大きい。

KSM:ロック保持705msが1.67msに

2つ目はKSM(Kernel Samepage Merging、同一内容のメモリページを統合して物理メモリを節約する仕組み)の逆引きマップ走査、rmap_walk_ksm()の最適化だ。

ZTEのシュ・シン(Xu Xin)氏とワン・ヤーシン(Wang Yaxin)氏が発見し、修正した。

KSMが管理するページの逆引きマップを走査する際、従来の実装はそのページに紐づくanon_vma(匿名メモリ領域を管理する構造体)配下のVMA(Virtual Memory Area、仮想メモリ領域)を全件走査していた。VMAの数が少なければ問題にならないが、数千〜数万のVMAが1つのanon_vmaにぶら下がると、走査はO(N)の計算量になる。

この走査中に取得されるanon_vmaのロックは、ページフォールト、メモリ回収、ページマイグレーション、コンパクション、mlockexit_mmap、cgroupの会計処理など、メモリ管理の広範な操作で共有されている。rmap_walk_ksm()がロックを数百ミリ秒保持すると、これらすべての操作がブロックされる。

シュ・シン氏はパッチシリーズの中で、ZTEのベンチマーク結果をこう報告している。

ロック保持時間が500ms超から2ms未満に短縮された。最悪ケースでは705msから1.67ms(最大)/1.44ms(平均)になった

修正内容は、anon_vma_interval_tree_foreachの走査にページオフセット範囲のフィルタリングを追加し、対象ページと無関係なVMAをスキップするというものだった。

誰が困っていたのか

この問題はVMAが大量に分割される環境で発生する。VMAの分割はfork()がなくても起きる。mprotectmadviseを繰り返し呼ぶだけで、1つのVMAが数千〜数万に分裂し、すべてが元のanon_vmaに紐づいたまま残る。

シュ・シン氏はパッチシリーズの中で具体例を挙げている。JVMやGoランタイムはヒープ領域にmmapを使い、後からガベージコレクションのバリアやガードページのためにmprotect(PROT_NONE)を呼ぶ。MySQLやPostgreSQLも、共有メモリバッファや匿名マッピングに対してmadvise(MADV_DONTNEED)で特定ページを解放する。いずれの操作もVMAを細かく分割する。

ZTEの本番環境では、KSMを有効にしたJavaアプリケーションで約20,000のVMAが1つのanon_vmaを共有していた。パッチ適用前のロック保持時間は、メモリコンパクションとページマイグレーション中のrmap walkで最大228msだった。

パッチの影響を受けないワークロード(VMAが大量分割されていない環境)では、追加されるのはページオフセットの比較1回分で、オーバーヘッドは無視できる。影響を受けるワークロードでは100〜500倍のロック保持時間の短縮になり、テールレイテンシの改善、メモリ圧迫時のスループット向上、コンテナのタイムアウト解消につながるとシュ・シン氏は述べている。

Linux 7.3 メモリ管理の2大改善
zsmallocKSM
対象圧縮RAM解放逆引きマップ走査
問題ロック競合ロック長期保持
改善幅最大1.83倍705→1.67ms
仕組みクラス検索を
ロック外に移動
VMAフィルタリング
を追加
影響先Android/サーバーJVM・MySQL等
貢献XiaomiZTE
※改善幅はそれぞれのベンチマーク条件下での値。zsmallocはRaspberry Pi 4Bでの最大値、KSMは2万VMA共有時の最悪ケース

501本の中の2本

今回のMMプルリクエストには、このほかにもdefrag_modeでのリクレイムストーム修正(Meta本番環境で発生した深刻なパフォーマンス退行への対処)、userfaultfdによるVMゲストメモリのワーキングセット追跡、HugeTLB割り当ての汎用化、VMAページオフセット処理の大規模リファクタリングなど、カーネルのメモリ管理を支える改善が並ぶ。

zsmallocのロック競合削減とKSMの逆引きマップ最適化は、どちらもカーネル内部の、ほとんどのユーザーが意識しない層の改善だ。だが、Androidのアプリ切り替え速度や、KSMを使う仮想化ホストのレイテンシ、zRAMを頼るサーバーのスワップ性能に直接影響する。

見えない層が少しずつ速くなり、その結果がユーザーのもとに届く。

501本のパッチはその一断面にすぎない。

関連記事

この記事を共有する

Read more