カーネル比較: 2.6カーネルで改善されたメモリ管理

ラージページからリバース・マッピングまで: 信頼性が高まり高速化も

2.6 Linuxカーネルでは大容量メモリの使用を改善するための手法がいくつか採用され、以前にも増して企業用途に向くようになっています。この記事では重要な変更のいくつか、つまりリバース・マッピング、メモリ・ページの大型化、ページテーブル・エントリーを高位メモリに保存する手法、より安定になったメモリ・マネージャなどについて概要を説明します。

Paul Larson (pl@us.ibm.com), Software Engineer, Linux Technology Center, FIT Team, IBM China Development Lab 

Paul LarsonはIBMのLinux Technology CenterのLinuxテスト・チームで働いています。昨年行った作業にはLinuxテスト・プロジェクトや2.5/2.6カーネル安定化、カーネル・コード範囲解析などがあります。



2004年 3月 03日

Linuxカーネルが成長し、成熟するにつれ、技術解析アプリケーションや、さらには巨大なデータベースを扱うような、非常に大きなシステムでLinuxを使用したいと考えるユーザーが増えてきました。こうした企業レベルのアプリケーションでは、高パフォーマンスのために大容量のメモリが要求されます。2.4 Linuxカーネルにもかなり大容量のメモリを取り扱えるような機構があったのですが、2.5カーネルにはさらに多数の変更が加えられ、より効率的に、より大容量のメモリが扱えるようになりました。

リバース・マッピング

Linuxのメモリ・マネージャでは、プロセスが使用するメモリの物理ページをページテーブルが追跡し、このテーブルが仮想ページを物理ページにマッピングします。こうしたページの一部は長期間に渡って全く使われず、スワップアウトの対象候補となるのですが、スワップアウトする前にそのページをマップしているプロセスを全て見つける必要があります。そうしないと、そのプロセス中でそのページに対するページテーブルのエントリーを更新することができません。Linux 2.4カーネルでは、そのページがそのプロセスによってマップされているかどうかを判断するために、どのプロセスのページテーブルもトラバースする必要があるので、大変な仕事でした。システム上で実行されているプロセスの数が増えるにつれ、こうしたページをスワップアウトするための作業もどんどん大きくなったのです。

この問題を解決するために、2.5カーネルにはリバース・マッピング、つまりRMAPが実装されました。リバース・マッピングは、ある(メモリの)物理ページをどのプロセスが使っているかを見つけるための機構です。全てのプロセスに対するページテーブルをトラバース代わりに、メモリ・マネージャには、各物理ページに対して、(現在そのページをマップする全プロセスの)ページテーブル・エントリー(PTE)へのポインターを持つリンク付のリストがあるのです。リンクされたこのリストはPTEチェーンと呼ばれます。PTEチェーンを使うと、ページをマッピングしているプロセスを見つけるスピードが非常に速くなります。これを図1に示します。

図1. 2.6でのリバースマッピング
Reverse-mapping in 2.6

もちろん何事もタダではありません。リバース・マッピングを使ってパフォーマンスを向上するには代償も必要なのです。最も明らかな代償はメモリのオーバーヘッドが増すということです。リバース・マッピングを追跡するためには一部のメモリを使用する必要があります。PTEチェーンの各エントリーはページテーブルへのポインターを保存するために4バイトを使用し、チェーンの次のエントリーへのポインターを保存するためにさらに4バイトを使用します。このメモリは低位メモリ領域から使う必要があるのですが、32ビットのハードウェアでは低位メモリはやや限られています。場合によってはリンク付リストを使う代わりに単一のエントリーを使うようにまで最適化することができるのですが、この方法はページダイレクトアプローチと呼ばれています。もしそのページへのマッピングが一つしかない場合には、リンク付リストの代わりに「ダイレクト」と呼ばれる単一のポインターを使います。この最適化が使えるのは、1つのプロセスのみがそのページをマップしている場合だけです。もし他のプロセスが後でそのページをマップしている場合には、そのページをPTEチェーンに変換する必要があります。与えられたページに対してこの最適化が実行中の場合にはメモリ・マネージャに知らせるためのフラグが立ちます。

リバース・マッピングによって複雑になる点もいくつかあります。プロセスがページをマップする時には必ず、こうしたページ全てに対してリバース・マッピングを確立する必要があるのです。同様に、プロセスがページのマップを解除すると、対応するリバース・マッピングも削除する必要があるのです。これは特にexit時には、共通に行われます。こうした操作全てはロックされた状態で行う必要があります。forkやexitを頻繁に行うアプリケーションでは、これは非常に高くつき、大きなオーバーヘッドとなります。

多少の代償が必要とはいえ、リバース・マッピングはLinuxのメモリ・マネージャには貴重な変更となりました。この手法を使う事で、ページをマップしているプロセスを見つける深刻なボトルネックが最小ですむようになったのです。リバース・マッピングのおかげで、大きなアプリケーションがカーネルに対して巨大なメモリを要求する場合や、複数のプロセスがメモリを共有している場合でも、システムのパフォーマンス低下が無くなり、拡張性も確保できるのです。リバース・マッピングはLinuxカーネルの将来バージョンに含められるように、現在もさらに改善が検討されています。


ラージページ

典型的な使い方では、x86システムではメモリ・マネージャはメモリを4 KBのページとして扱いますが、実際のページサイズはアーキテクチャに依存します。大部分の使い方では、メモリ・マネージャが一番効率良くメモリを扱えるのは、このサイズのページだと言えます。ところが一部のアプリケーションでは非常に大量のメモリを使います。巨大なデータベースはその好例と言えます。各プロセスがマップする各ページに対して仮想アドレスを物理アドレスにマップするためには、ページテーブル・エントリーも作る必要があります。もし1 GBのメモリを4 KBのページでマップするアプリケーションだとすると、ページを追跡するには262,144のページテーブル・エントリーが必要になります。もしページテーブル・エントリーがそれぞれ8バイトを消費すると、マップするメモリ1 GB毎に2 MBのオーバーヘッドになります。これだけでもかなりのオーバーヘッドですが、そのメモリを複数のプロセスが共有している場合にはもっとひどくなります。この場合には、その同じ1 GBのメモリをマップしているプロセスそれぞれが自分のページテーブル・エントリーに2 MB分のメモリを消費してしまうのです。プロセスが多数ある場合にはオーバーヘッドで浪費されるメモリがアプリケーションが使用するメモリを上回ってしまうかも知れません。

この問題を軽減するには、使用するページのサイズを大きくする事です。最近のプロセッサーの大部分は少なくともラージページとスモールページをサポートしていますが、それ以外のサイズもサポートしているものもあります。x86では、物理アドレス拡張(PAE)がオンになっているシステムであれば、ラージページのサイズは4 MBまたは2 MBです。上の例でラージページのサイズとして4 MBを使うとすると、先の1 GBのメモリをマップするのに262,144も必要なく、256のページテーブル・エントリーだけですむのです。これはつまりオーバーヘッドとしては2 MBも要らず、2,048バイトだけですむという事になります。

大きなサイズのページを使うとtranslation lookaside buffer (TLB)の使い残しも減るので、パフォーマンスも向上します。TLBはページテーブルに対する一種のキャッシュですが、これを使うとテーブルにリストされているページに対する仮想メモリから物理メモリへの変換が、より高速に行えるようになるのです。当然ながらTLBが保持できる変換の数は限られます。ページが大きくなれば実際のページ数は少なくなり、より大量のメモリを収容できるようになります。ですから使うページが大きければ大きいほど、(ページサイズが小さい時に比べて)TLBで参照されるメモリの量も多くなるのです。


ページテーブル・エントリを高位メモリに保存する

32ビットのマシンでは通常、ページテーブルは低位メモリにしか保存できません。この低位メモリは物理メモリの最初の896 MBに限られており、カーネルの残りの大部分もこの領域を要求します。アプリケーションが大量のプロセスを使用し、大量のメモリをマップするような状況では、低位メモリはすぐに残りが僅かになってしまいます。

ところが今度2.6カーネルに入ったHighmem PTEと呼ばれる設定オプションを使うと、ページテーブル・エントリーを高位メモリに置けるようになります。これによって、どうしても低位メモリに置く必要のある他のカーネル・データ構造のために低位メモリを解放する事ができるのです。その代わり高位メモリに置かれたページテーブルのエントリーを使うプロセスは少し遅くなりますが、非常に多くのプロセスが実行しているようなシステムでは、ページテーブルを高位メモリに保存することで、低位メモリをより有効に使うことができるのです。

図2. メモリ領域
Memory regions

安定性

安定性が向上したことも2.6のメモリ・マネージャで改善された重要な点です。2.4カーネルがリリースされた直後から、ユーザーはメモリ管理に関連した安定性の問題に悩む事になりました。メモリ管理がシステム全体に及ぼす影響を考えると、安定性は最も重要性が高い問題と言えます。問題の大部分は解決されたのですが、その解決方法は本質的にはメモリ・マネージャの中身を取り除き、その代わりに簡略化したものと置き換えただけでした。このためLinuxの販売業者には自分たちのディストリビューション用にメモリ・マネージャを改善する余地ができたわけです。これは言い換えると、2.4のメモリ管理機能はどのディストリビューションを使っているかによって大きく異なると言う事でもありました。そうした事態がまた起きるのを避けるために、2.6のカーネル開発で一番厳しく検証された領域はメモリ管理なのです。新しいメモリ管理用のコードはローエンドのデスクトップ・システムから、大規模で企業レベル、複数プロセッサーのシステムに至るまで、あらゆるシステムでテストされ、最適化されています。


まとめ

Linux 2.6カーネルで行われたメモリ管理の改善に関連してこの記事で説明したのは、機能のごく一部でしかありません。変更されたものの大部分は小さなものですが、重要性は変わるわけではありません。こうした変更すべてによって2.6カーネルのメモリ・マネージャのパフォーマンスが向上し、また効率や安定性も向上しているのです。Highmem PTEやラージページといった一部の変更はメモリ管理が引き起こしたオーバーヘッドを減少させます。その他、リバース・マッピングなどのような変更は、ある非常に難しい領域でのパフォーマンスを向上させます。こうした具体的な例を選んで説明したのは、Linux 2.6カーネルがより企業向きのハードウェアやアプリケーション用として、いかに調整・機能向上されているかがよく現れていると思ったからです。

参考文献

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux
ArticleID=226824
ArticleTitle=カーネル比較: 2.6カーネルで改善されたメモリ管理
publish-date=03032004