LinuxCon Japan 2012を3倍楽しむための基礎知識

第6回Linux Kernelメモリ管理最新動向その2]

2012年6月6日~8日にLinuxCon Japan 2012 が開催されます。ここではLinux Kernelの最新技術の発表や議論がいろいろ行われるのですが、このカンファレンスを楽しむ手助けとなる記事を…ということで、最近のLinux Kernelのメモリ管理の以下のトピックについて、2回に分けて紹介しています。

第2回目の今回は、以下のテーマについて説明します。

  • ファイルシステム、デバイスと連携したエンハンス
  • メモリ資源管理機能(cgroup)
  • CleanCache

ファイルシステム・デバイスと連携したエンハンス

I/O less dirty throttling

Linuxでは「ファイルシステムに書き戻す必要のあるデータを持ったページ」をdirty pageと呼びます。これらのページはファイルシステムにデータを書くまでは破棄できませんから、メモリ回収前にI/Oを行う必要があります。しかし、I/Oをする際にもメモリが必要になることはよくあります。メモリの大部分がdirtyになってしまうとメモリ回収に悪影響がありますので、Linuxはdirtyページの総数を一定以下に保つようにしています。この一定以下に保つ処理をdirty throttleと呼び、dirty page管理の閾値をdirty limitと呼びます。この処理ではファイル等への書き込みの途中でdirty page量とdirty limitを比較し、dirty page量がdirty limitを超えないように書き込みを抑制します。

以前は、dirty pageの量がdirty limitを超えた場合、limitを超えたthreadが直接「ファイルシステムへの書き戻し」を呼び出していました。そうするとdirty page量が減るまではthreadは実行を止め、アプリケーションも進みません。この書き込みは、I/Oに対する酷い外乱要因となってファイルシステムのパフォーマンスを悪化させるため、アプリケーションが突然遅くなるという問題がありました。

この問題に対し、dirty pageがlimitに近くなった場合、実行中のthreadからは直接にはI/Oを出さないようにする修正がマージされました。新しい dirty throttling ではdirty page の量がシステムに設定されているdirty limitに近づくと、書き込みを行っているthreadの書き込み速度を抑制します(少し寝かせる⁠⁠。

この抑制の仕方がポイントで、今までの実装ではdirty limitになった瞬間に突然遅くなっていた(書き戻しを始めるため)のに対して、新しい実装ではdirty limitに近づくと、徐々に書き込みを行うthreadのスピードが遅くなります。そのため、突然threadがブロックされて大量の書き戻しを開始する処理は無くなり、ファイルシステムへの外乱要因も減るというわけです。

この実装は非常に複雑で、筆者も理解しているとは言い難いのですが、幸いなことに実装者であるWu Fengguang氏(Intel)によるプレゼンテーションが LinuxCon Japan 2012で行われます。ユーザの中でもdirty_ratioをチューニングしている方がいらっしゃると思いますのでこ、の機会に聴講・質問されてみてはいかがでしょうか?

Swap

Swapについてもいくつか話題がありますので、簡単に紹介します。

Swap over NFS, swap over NBD

1つ目は Swap over NFS, Swap over NBD と呼ばれる機能で、Mel Gorman氏(Suse)から提案されています。この機能はネットワーク越しにswap deviceを使えるようにします。Swap Over NFSはswap deviceにNFSを用いたswap、Swap Over NBDはNetwork Block Deviceを用いたswapです。これらの機能はnetworkの先にswapデバイスを作り、メモリ回収の延長でネットワークを使用してリモートマシンにメモリの内容を移します。

Diskless clientでは必要だ、と言われると、そうかもね…という気になるのですが、根本的な問題として、メモリが不足して回収の延長から呼ばれるのに、ネットワーク通信用にメモリを確保しなければいけない点が挙げられますし、モバイル系のシンクライアントでは応答が遅すぎて意味がありません。下手をすると通信用のメモリ確保でデッドロックしますので、Slabアロケータ等にきちんと手を入れて実現する必要があります。現在提案されているものはそのあたりは回避できている、ということですが、提案されてから結構時間が経過しているのに、いまだにマージされるのかどうか見えていません。マージされるには、使いたい人からのアピールやテスト協力等が重要な鍵になりそうです。

Swap over eMMC

2つ目は、フラッシュデバイス上にswapを作った場合の問題があります。Linaroグループの人からの最初の投稿をベースに説明すると、主な問題は、現在のswapの実装がハードディスクを前提としており、フラッシュデバイスの特性とswapの実装がマッチしていないことから生じています。

第1に、swap outが発生する際には4KBずつI/Oが発行されますが、フラッシュデバイスの性能が出るのは32KBや64KBの連続書き込みであるということ。第2はDISCARD(TRIM)サイズの問題です。swapはswap cluster という内部実装を持っていて、このcluster単位でswapエントリの取得等が行われています。このcluster単位を使ってフラッシュデバイスのDISCARD(TRIM)という処理も呼ぶのですが、現在の実装ではclusterの大きさは1MBであり、これが現在の主流のデバイスのDISCARDサイズ、4M/8Mに合っていないというのが彼らの指摘です。

ところでDISCARDとは何でしょうか? フラッシュデバイスには、ウェアレベリング(Ware Leveling)という言葉があります。これは、メモリ素子は書き込みを行うと劣化していくので、1ヵ所に集中して書かずに、できるだけ平準・分散して書き込みを行うことでフラッシュデバイスの寿命を延ばす処理です。この処理のため、フラッシュデバイスは管理しているメモリのうち、どこが使用中でどこがそうではないのかを管理し、ゴミ集め(GC/Garbage Collection)なども行っています。DISCARDは、デバイスに「この部分はもう使ってないよ」と教える処理です。これによりデバイス内部でのGC等がスムーズになりウェアレベリングが楽になります。

これに続く議論の中で指摘されているのが、eMMCデバイスはreadのアクセスレイテンシはwriteよりも圧倒的に低い、だから、write負荷を下げ、read負荷が高くなるようにメモリ回収処理を修正していく方向があるのではないか、というものです。つまり、できる限りcleanなページを追い出し、dirty pageのswap書き込みをできるだけ抑制することでシステム全体の速度を上げられるのではないか?という議論です。今のところ具体的なパッチによる提案等は行われていません。しかし、フラッシュデバイス・不揮発性メモリ関連はこの先しばらくトピックになりそうですね。

メモリ資源管理機能(memory cgroup)

メモリ資源管理機能は、筆者もメンテナの一人を務めていますが、近年は開発者が増加しており開発や議論も活発です。LinuxCon Japan でも memory cgroup の動向について話をさせて頂く予定ですが、最近の変化、新機能についてここで少し触れたいと思います。なお、memory cgroupはユーザのメモリ使用量の上限を制御するための機能で、任意のプロセス群のメモリ使用量を制限することができます。

LRUの一本化

Linuxではページ管理のためにLRUというリスト構造を用いています。以前のメモリ資源管理の実装では、システム全体のLRUとメモリcgroup用のLRUの2つのLRUの2重管理をしていました。このため、ページごとにLRUのリストポインタを持つ必要があり、1ページ(x86では4096bytes)に対しポインタ用に40bytes(64bitの場合)のメモリを使用していました。

昨年、Johannes Weiner氏(Red Hat)がLRUを一本にしました。現在はmemory cgroupもこのシステム全体のLRUを使用しています。このシステム全体のLRUは、memory cgroupごとのLRUの集合として扱われています。Johannes氏の他のパッチとあわせ、memory cgroup の使用メモリは1ページあたり16バイトにまで削減されました。現在、1ページあたり8バイトまで削減する予定で議論されており、将来的には完全に無くす案も出ています。

User memory以外の管理

従来、メモリ資源管理の制御対象のメモリは、ユーザメモリとファイルキャッシュのみでした。最近になり、これら以外のメモリを管理する動きが出てきました。実装済(ほぼ済のみも含む)のものとしては、tcp のメモリ制限とhuge page のメモリ制限機能が新たに加わっています。また、現在、カーネルメモリ(slab)についても制限を行うパッチが投稿され、レビューが行われています。カーネルメモリ制限は多くの人々が欲しがっているのですが、アカウンティングを行うことによるコスト、制御対象、粒度等について、まだ議論が続いています。

ソフトリミット

soft limitの再実装についても議論が行われています。soft limitというのは、このlimit値を超えられるけれども、超えている場合は、システムのメモリが足りなくなってきたら優先的に回収対象にされるというヒント値であり、memory cgroup毎に設定可能です。でも、運用した時に、soft limitが思っているように動作していないという指摘が度々あり、再実装が検討されています。soft limitはシステムのメモリ回収全体に影響を与える機能であるため、検討は慎重に行われています。

CleanCache

CleanCacheは、カーネルのメモリ管理に対して外付けの形で確保したメモリの管理機能です。⁠Cache⁠という名の通り、メモリキャッシュの一種で、基本的にはファイルキャッシュの為に使います。⁠外付けの形で」というのは、カーネルとのインタフェースはあるけれども、内部実装についてはカーネルは感知しない、Black Box のような外部メモリ管理、という意味です。図を使ってCleanCacheの役割を説明しましょう。

図1 CleanCacheの役割
図1 CleanCacheの役割

ファイルキャッシュというのはファイルシステムの内容を一時的にメモリに保持しておく機能で、diskへのI/Oを削減する効果があります。Linuxでは必要な場合にファイルキャッシュの中身を捨てて解放し、メモリを回収しますが、CleanCacheはこの処理をフックし、キャッシュを捨てる前にその内容を外部キャッシュ用のドライバに渡します(A⁠⁠。

コピーされたデータをどう取り扱うか(保存するか否か)は外部キャッシュ側で判断され、カーネルにはわかりません。再度そのファイルにアクセスがあった場合、カーネルは disk に I/Oを出す前に CleanCacheを呼び出し、外部キャッシュにデータがあるかどうかを問い合わせ(B⁠⁠、データがあればCleanCacheからデータをコピーしてDisk I/Oを回避します。

この場合、Disk I/Oを回避できます。なければDiskにI/Oを出します。つまり、CleanCacheはファイルキャッシュをLinuxメモリ管理のファイルキャッシュとCleanCacheの2段構造に変更します。2段階構造にすることで面白いことができるようになります。

第1は仮想化環境です。ホスト側で確保したCleanCache用メモリを仮想化環境のゲストの外付けのメモリとして設定し、ゲストから追い出されたデータをホスト側にキャッシュすることができます。ホスト側でキャッシュできるので、複数のゲストで同じ内容のメモリがある場合にまとめることができます。また、ホスト側にキャッシュを持つので、ゲストは割り当てられた資源以上の性能を出すこともできます。

第2は圧縮です。すでにいくつかのディストリビューションには取り込まれている機能ですが、zramやzcacheという機能がCleanCacheのフレームワークで実装されています。zcacheではファイルキャッシュから追い出されたデータをCleanCache内で圧縮し保持します。これにより、I/Oを大幅に減らすことができるだけでなく、スワップ(zram)として使えばI/Oの無いスワップデバイスの構築も容易にできます。CleanCache機能のSwap向けフックはFrontSwapと呼ばれているのですが、現在はFrontSwap内のデータを実際のスワップデバイスに書き出す処理がないことが、upstreamへのマージのネックになっているようです。

ファイルキャッシュは中身を捨ててもまたファイルシステムから読んでくればいいため、CleanCacheをファイルキャッシュに使う場合は、⁠最近アクセスされたデータを保持するがあふれたら中身を捨てる⁠キャッシュ機能としての動作が期待できますが、FrontSwapの場合、swapなのでアクセスが無くても中身は捨てられません。今のままでは「スワップデバイス書き込みが行えない=中身は捨てられない」ということで、ずっとメモリを占有することになり、Cacheとしては動作していません。圧縮してもメモリを占有するのは変わりませんから、普通のswapと同じように必要になりそうな最大サイズを見切ってzram用のメモリを割り当てる必要があります。大きなシステムの場合あまりに大きいzramを持つくらいならそのままメモリに使った方が有効だということになりかねません。

第3はネットワークを介した他ホストのメモリ利用です。現在、これを実現するRAMSterという機能がstagingドライバに入っています。この機能により、クライアントとして動作しているマシンは、サーバとして動作しているマシンとの間で CleanCacheのデータを送受信できるようになります。これにより、外部マシンのメモリをネットワーク越しにファイルキャッシュとして利用できます。このため、RAMサーバを1つ立て、キャッシュサーバとして運用する用途も考えられているようです。

終わりに

メモリ関連の最新動向の話をしましたが、この記事の執筆中にも新しい提案が行われている状況で、非常に活発に議論/変更が行われています。LinuxCon Japanのセッションとは直接関係しない話題もあったかもしれませんが、会場で関係者・開発者を捕まえて、ぜひこれらの情報をもとにして、議論してみてください。

おすすめ記事

記事・ニュース一覧