Linuxメモリ管理の最先端を探る


小崎 資広
2008/5/22


アイコン VM(仮想メモリ)の改善

 昔からのLinuxユーザーの方は、カーネル2.4の時代に、一時期VM(仮想メモリ)が不安定で悩まされていたことを覚えている方もいるかもしれません。

 現在のVMは、Andrea Arcangeliの作成した割とシンプルな設計なVMに、Rik van Rielの作成したページフレームからページテーブルエントリを逆引きするためのreverse mappingという機能を追加したものが基本となっています。

 これは、コードの複雑さと性能の間でバランスの取れた、なかなか評判のいいものだったのですが、カーネル2.6の登場から約5年がたち、だんだんアラが目立つようになってきました。

 というのも、当時は一般的なパソコンのメモリ量は256M〜512Mbytes程度で、サーバでも4Gbytesの壁を超えるようなマシンはまれでした。しかし、DRAMの急激な低価格化に加え、Linuxが急速にハイエンド市場に受け入れられていったことにより、いまや1Tbyte(テラバイト)のメモリを搭載したサーバも登場しています。これだけスケールアップしてしまうと、設計当時とはボトルネックの見積もりがずれてしまっているわけです。

 Rik van Rielは、搭載メモリ量が100Gbytesを超えたあたりから、現在のVMではスケーラビリティの問題が発生すると主張しています。

 現在のアルゴリズムでは、ページフレーム回収が動作するとページフレームのLRUリスト注2)を走査し、最近アクセスされていない(Access bitが立っていない)ページを探します。ところが、メモリ量が増えるとその分メモリ不足が発生しにくくなり、ページフレーム回収がまれにしか動きません。すると、いざページフレーム回収論理が動作したときには、非常に多くのページにAccess bitが立っていることになります。

注2:LRUとはLeast Recently Usedの略であり、ざっくりいうと、最後にアクセスされた時刻を基にソートされているようなデータ構造のことを示します。キャッシュについては、使っていないデータから破棄することが望ましいので、多くのOSがLRUの派生アルゴリズムをメモリ管理に採用しています

 さて、ここで簡単な計算をしてみましょう。x86_64 Linuxでは、ページの大きさは4kbytes、ページディスクリプタの大きさは64byteです。すると、メモリを100Gbytes搭載したシステムでは2621万4400ページ(=100Gbytes/4kbytes)がシステムに存在し、ページディスクリプタが1600Mbytes(=100Gbytes/4kbytes×64bytes)のメモリを使用することになります。

 つまり、すべてのページにAccess bitが立っている状態でページフレーム回収処理が呼ばれると、2500万回以上のロックの取得解放処理を伴う、1600Mbytesのランダムメモリアクセスが発生するわけです。何となく重そうな処理であることは容易に想像いただけるでしょう(もちろんこの計算は非常に大ざっぱなものです。実際にはもっと複雑なことをしているので、さらに遅くなります)。

 また、さらに悪いことに、近年CPUのマルチコア化が進み、CPU数が多いサーバが増えてきました。これは通常のケースでは性能を向上させますが、上記のようなワーストケースでは非常に多くのロック競合が発生し、パフォーマンスが劇的に劣化してしまいます。

 この問題に対する解答として、Rik van RielLee SchermerhornVM pageout scalability improvementsパッチセットを提案しています(実は筆者も開発に参加していて、筆者のパッチもたくさんマージされているので思い入れがあります)。

 このパッチセットは、主に以下の2つの改善をしています。

 1点目は、mlockされたメモリの管理方法の改善です。いままではmlockされたページも通常のページと同じように、LRUにつながっていました。しかしmlockされているページがスワップアウトされることは決してありません。これをチェックするのは、純粋にCPUサイクルの無駄です。

 そのため、回収不可能なページを管理する新しいLRUリストを新設し、mlockされたページをそちらに移せば、ページフレーム回収を高速化できます。これはほかのOSで当たり前のように行われている最適化ですが、Linuxでは行われていなかったのです。

 2点目は無名ページ管理の改善です。これだけメモリが増えるとスワップはまず発生しないので、無名ページのチェックの負荷が相対的に大きくなってしまいました。そのためファイルキャッシュと無名ページの管理LRUを分離し、普段はファイルキャッシュを管理するLRUだけをチェックするようにしました。

 また無名ページ管理LRUの無名ページの特性に合わせて、deactivateの論理を修正しています。無名ページは常にプロセスにマップされているので、ファイルキャッシュと同じように「マップされているページのページテーブルエントリのAccess bitが立っていたらactive listに移動」というルールを用いると、ほぼすべてのページがactive listに移動してしまい、回収が非効率になってしまうためです。

VMの改善
VMの改善

 Linuxを使っていてスワップ発生とともに急激に応答性が悪化した経験のある人は、このパッチによって幸せになれるかもしれませんね。

 このパッチはまだ-mmにもマージされていませんが、将来が楽しみですね。

アイコン 仮想化関連の改善

 近年、仮想化技術が急速に普及してきており、LKMLにも仮想化関連のパッチがしばしば投稿されるようになりました。

■MMU notifier

 これはKVMコミュニティから出てきた提案で、2008年早々にAndrea Arcangeliがスタートさせました。

 KVMでは、shadow pteという仕組みを使ってゲストOSのメモリを管理するのですが、ホストOSでは、このshadow pteが参照しているメモリをスワップアウトすることはできませんでした。もしそれをしてしまうと、ゲストOSから見るとカーネルすら知らない間にメモリがスワップアウトされてしまうことになり、正常に動作できないからです。

 しかし、ゲストOSの中にはあまり参照されていないページも大量にあります。これらをスワップアウトしたいという要求がありました。

 この問題を解決するために出てきたのがこのMMU notifierです。動作原理は簡単で、Linuxはページをスワップアウトさせるときにまずページをアンマップし、pteを無効化します。ここにフックを仕込んでおいて、ゲストOSに通知を上げることができれば、ゲストOSのメモリ管理が破たんすることなくスワップが実現できます。

 これに反応したのがChristoph Lameterで、「SGIはそれを実現できるXPMEMというパッチを持っているので、KVMもそれを使うのがよい」と提案しました。

 XPMEMというのはSGIのスパコンで使われているカーネル拡張です。特殊なハードウェアと組み合わせることにより、クラスタの別マシンのメモリをネットワーク越しにmmapして、アプリケーションが搭載メモリをはるかに超えるメモリにアクセスできるという発想の、その強引さに感動が止まらないすてきな機能です。

 その後、議論は一進一退を繰り返しています。両機能が統合されたパッチができかけると別の誰かがパッチが複雑過ぎると苦情をいうので、なかなか話がまとまりません。個人的には、SGIのRequirementが特殊過ぎて余人には理解し難いのが一番の原因だと思っていますが……。

 現在までに、Andrea ArcangeliChristoph LameterNick PigginRusty Russellの4人がそれぞれ別のMMU notifierパッチを提案しており、オープンソース特有のガチンコ・パッチバトルが繰り広げられています。早く議論がまとまって-mmにマージされるといいですね。

アイコン 期待の新機能、memcgroup

■memcgroup

 これは、2007年で一番盛り上がった機能かもしれません。memcgroupは、SolarisのZone/Containerに相当する機能であり、システム内に仮想的なパーティションを作り、特定のプロセスの集合が使用できるメモリ量を制限できる機能です。大きなくくりでは「Yet Another Virtualization」といえるかもしれません。

 主にBalbir SinghPavel EmelyanovKAMEZAWA Hiroyukiの3人によって開発・メンテナンスされています。余談ですが、Pavel EmelyanovはOpenVZの開発者で、今後OpenVZはmemcgroup上のミドルウェアに移行するのではないかといわれています。

 使い方は簡単で、cgroupファイルシステムをマウントしたうえで、

# mkdir /cgroups/gruop0
# echo $$ > /cgroups/group0/tasks
# echo 4M > /cgroups/group0/memory.limit_in_bytes

のように実行すると「group0」という名前のグループに自プロセスを登録し、そのグループのメモリ使用量の上限を4Mbytesに制限することができます。

 Xenなどの仮想化機能に比べた利点はいくつかありますが、

  • OSを2段重ねにするよりも軽い、速い
  • システムディスクを別に用意する必要がないのでお手軽
  • 使い方が簡単なのでミスが起きにくい
  • 制限値の動的な変更が簡単

といったところでしょうか。別のいい方をすると、「ホストOSもゲストOSもLinuxなら、わざわざ仮想マシンを用意するメリットは少ない」という哲学に基づくアプローチなのだと思われます。

仮想マシン
いわゆる仮想マシンの仕組み
memcgroup
memcgroupはもっとシンプルになる

 この方式ですと、DVDを焼くのが失敗しないようにメモリをパーティショニングしたい、といったカジュアルな用途にも使えるわけで、デスクトップユーザーも取り込める可能性がありそうです。

 この機能は2.6.25でマージされました。もっとも、マージされたのは基本機能のみであり、さまざまな拡張および性能改善が活発に議論されています。たぶんあと何カ月かすると拡張も一段落つくと予想されます。その時期になれば、もう少し詳しくcgroupの詳細や勘所を書くことができるかもしれません。期待していてください。

2/2

Index
Linux Kernel Watch 番外編
 Linuxメモリ管理の最先端を探る
  Page 1
 フラグメンテーションに対する改善
Page 2
 VM(仮想メモリ)の改善
 仮想化関連の改善
 期待の新機能、memcgroup

連載 Linux Kernel Watch


 Linux Squareフォーラム Linuxカーネル関連記事
連載:Linux Kernel Watch(連載中)
Linuxカーネル開発の現場ではさまざまな提案や議論が交わされています。その中からいくつかのトピックをピックアップしてお伝えします
連載:Linuxファイルシステム技術解説
ファイルシステムにはそれぞれ特性がある。本連載では、基礎技術から各ファイルシステムの特徴、パフォーマンスを検証する
特集:全貌を現したLinuxカーネル2.6[第1章]
エンタープライズ向けに刷新されたカーネル・コア
ついに全貌が明らかになったカーネル2.6。6月に正式リリースされる予定の次期安定版カーネルの改良点や新機能を詳しく解説する
特集:/procによるLinuxチューニング[前編]
/procで理解するOSの状態

Linuxの状態確認や挙動の変更で重要なのが/procファイルシステムである。/procの概念や/procを利用したOSの状態確認方法を解説する
特集:仮想OS「User Mode Linux」活用法
Linux上で仮想的なLinuxを動かすUMLの仕組みからインストール/管理方法やIPv6などに対応させるカーネル構築までを徹底解説
Linuxのカーネルメンテナは柔軟なシステム
カーネルメンテナが語るコミュニティとIA-64 Linux
IA-64 LinuxのカーネルメンテナであるBjorn Helgaas氏。同氏にLinuxカーネルの開発体制などについて伺った

MONOist組み込み開発フォーラムの中から、Linux関連記事を紹介します


Linux & OSS フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Linux & OSS 記事ランキング

本日 月間