検索
連載

Linux Storage Filesystem/MM Summit 2014からの便りLinux Kernel Watch(1/2 ページ)

お久しぶりです、Linux Kernel Watchが帰ってきました。3月に行われた「Linux Storage Filesystem/MM Summit 2014」の主なトピックを紹介します。

Share
Tweet
LINE
Hatena

 皆さん、お久しぶりです。私は今ボストンで、米レッドハット常駐という立場でRed Hat Enterprise Linux(RHEL)開発に携わっています。

 今回はサンフランシスコ近郊のナパバレーで2014年3月24〜25日に行われた「Linux Storage Filesystem/MM Summit 2014」(以下LSF/MM)の中から面白かったトピックをピックアップしてお届けしたいと思います。

 LSF/MMはLinux Foundation主催で行われる招待制イベントで、ストレージ、ファイルシステム、メモリ管理の中心的開発者を招待し、技術的課題を集中議論します。近年はKernel Summitで技術的課題を扱うことが無くなってしまったので、個人的には一番面白いイベントです。読者の方々も楽しんでもらえれば幸いです。

FacebookにおけるLinux運用と悩み

 しばらく前にFacebookに移籍したbtrfsメンテナーのChris Masonから、FacebookにおけるLinux運用体制について紹介があり、さらにFacebookのインフラチームからのLinuxへの改善要望も寄せられました。

 それによると、Facebookは“devops”でインフラを運用していて、デプロイは平均1日2回。利用しているカーネルは、

  • 2.6.38
  • 3.2.x+250パッチ
  • 3.10.x+60パッチ

の3種類だそうです。ここで当てているパッチはほとんどがnetとtrace関連で、ほんの少しだけMMが混じるとか。バックエンドはMySQL、Hadoop、RocksDBなどさまざま……とざっと紹介した後、「台数が多いのでカーネルバグがあると大変な目に遭う。だからテストをものすごく強化している」と報告。3.10の「pipe bug」では毎日500台クラッシュするので泣きそうだった(注1)という体験談を披露しました。

 次に話はLinuxの問題点に移り、Facebookが一番問題だと思っている機能は「CFQ」だとスクリーンに大写し。会場が爆笑します(注2)

 それから話はもっと細かい個々のトピックに移ります。一番よくトラブルが起きるのがスピンロック競合で、「みんなロック競合に気を付けて設計してね」と注文しました。

 また「memcachedがユーザーランドで独自にスピンロックを実装しているけど、ロックを持っている時もプリエンプションしてしまって性能が出ないから、プリエンプションをコントロールしたい。可能なら、カーネルが持っているようなFIFO付きの賢いスピンロックが欲しい」と悩みを紹介します。残念ながらこれについては即座に、「非特権ユーザーがプリエンプションを拒否できたらいくらでも悪用できる」と反論されていました。

 IOについては、fine grained IO priorityでioniceをまともにしたい、ということでした。これについては後述するPostgreSQLの項目で、IO priorityの問題をまとめて紹介します。

 次がLinuxのページキャッシュについての注文。さまざまなプロセスがさまざまなログを吐くので、放っておくとメモリがログファイルのページキャッシュでいっぱいになってしまい、性能に影響します。今はfadvise(DONTNEED)で、手動でありとあらゆるログを定期的にメモリから落としているけれど、これは全自動でそうなるべきじゃないのか、というわけです(注3)

 ここで画面に、tracepointを使って採取したsyscall latencyのグラフを写し出し、「ごくまれに、通常の数百倍も時間がかかっている処理があり、サービス品質的に大問題。surprise largeallocationは本当にやっかいな問題だね」とコメントしました。

 また、emergency cgroupのような機能を作り、虎の子メモリをとっておくことができるようにしたいとも要望しました。残念ながらどういう機能か詳しく紹介されなかったので、この場では突っ込んだ議論はなし。Michal Hockoの「memory cgroupにlow limit(メモリ最低保証)を追加する提案」と類似のものかと推測したのですが、たぶん同じ理由でダメでしょう(注4)

 最後に、dmesg問題について、「いくら何でもgrepで監視するのはlow level過ぎるし、性能的にも問題がある、Structured loggingが必要」と訴えました。残念ながら類似の提案は過去何回もLinusに否決されてきた経緯があるため、James Bottomleyから今年のKernel SummitでLinusに直接言うようアドバイスがありました。

 Googleと同じような悩みもあれば全然違う悩みもあって面白いですね。

注1:その場ではどれのことか言ってなかったけど、たぶんこれ(https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=b0d8d2292160bb63de1972361ebed100c64b5b37)のことです。

注2:CFQのメンテナのJens Axboeは最近Facebookに移籍、Chris Masonのチームに合流した。さらに言えば、このセッションをChrisと共同発表するはずだったがドタキャンし、会場に姿を表さなかったので、「お前ら、ここじゃなく会社で話し合うべき」と突っ込まれていました。

注3:筆者もそう思います。コードを見たけれど、できない理由がないように見えます。

注4:Michal Hockoは今回、memory cgroupにメモリ最低保証を追加する提案を行いました。しかし、「NUMAマシンでは総量としては足りていても、個々のノード単位ではメモリ不足でOOMとかが発生するので、NUMAを意識してないmemory cgroupでは保証のしようがない」「デザインとして壊れている」と批判され、同意が得られませんでした。


PostgreSQLの憂鬱

 今年はPostgreSQLのエンジニアを特別招待し、データベース開発上の問題点について議論するセッションが設けられました。数日後のCollaboration Summitでも同様のセッションがあったのですが、ほぼ同じ議論だったのでまとめて紹介します。

 今回PostgreSQL開発者からは、Double Buffering、性能劣化(zone reclaim mode、THP、compaction)、sync問題、テストについて課題提起がありました。その全ては紹介できないため、主なものをピックアップしてご紹介します。

 話の前提として、PostgreSQLのアーキテクチャを簡単に紹介します。PostgreSQLはDBにしては珍しくDirectIOを使っておらず、全て普通のbuffering IOにて読み書きを行います。またクラッシュリカバリを実現するために、あらゆる書き込みはいったんWAL(Write Ahead Log)というジャーナリング領域に書き込まれ、チェックポイント処理によりWAL書き込みが(fsyncなどにより)ディスクに書き込まれたことを確認してから、本書き込みを行います。

 さて、クラッシュリカバリの制約からPostgreSQLはmmapを使わず、read/writeを使っています。mmapを使うとWALに書き込まれるまで本書き込みを開始しないという制約が満たせないためです。writeを使うと、PostgreSQLプロセス内のバッファーとカーネルのページキャッシュに重複したデータが乗るため、メモリ使用量が増大し、余分なメモリコピーによる性能低下という問題が発生します。これが「double buffering問題」です。

 残念ながらこちらについては、本番議論前の事前ディスカッションでPostgreSQLコミュニティからさまざまな異なるアイデアが提出され、かつどれも副作用が大き過ぎると判断されました。例えば、ディスク書き込みのタイミングを制御できるmmap、というアイデアが出ましたが、実質非特権プロセスにmlockを許可するのと同じことになってしまうのでセキュリティ上問題があるという具合です。このため、今回議論はなし。カーネルコミュニティからは「コンピューターサイエンス的に綺麗な解があれば、対応するのはやぶさかじゃないんだけどね」とコメントが付きました。

 今回一番議論を読んだのは、チェックポイント処理におけるfsync性能問題です。PostgreSQLコミュニティからは"The problem is not that fsync() is too slow; instead, it is too fast."と、大変ユニークな表現で問題が説明されます。

 どういうことかというと、PostgreSQL的にはチェックポイントなんてバックグラウンドでいくらでも遅延してもいい低優先度処理なのに、カーネルが低優先で処理してくれず、他のIOが滞ってしまうのです。これは特に、DBをシステムボリュームと同じディスクに置いた時に問題になります。

 Linuxのブロックレイヤーは「sync queue」と「async queue」という2本のキューを持っていて、readがsync writeとasyncとを使い分けることによりreadがwriteより優先される仕様となっています。なぜならreadが滞ると、アプリがその間ハングしてしまい、そのレイテンシがユーザーエクスペリエンスに直結するからです。これと同様の理屈で、fsyncで待っている間プロセスが先に進めないので、fysncはreadと同じくsync queueを使って優先処理されてしまうのです。

 これは一般にはいい処理です。例えば以前この連載で、FirefoxはUIスレッドでfsyncを呼んでいて問題になったと紹介しましたが、Linuxのデスクトップアプリの中には同様にGUIスレッドからfsyncを呼んでいるコードが数多くあり、fsyncが遅いと動きがカクカクしてしまいます。

 また、マニュアル上ではioniceという機能が存在することになっているのですが、全く機能していません。理由の1つは、IO priorityに対応しているのはCFQスケジューラーしかないのですが、このスケジューラーは性能が悪く、DB関係者で使っている人は誰もいません。理由の2つ目は、たとえCFQを使っていても、fsyncなどを使い大量のIOを一気に発生させるケースではIO priorityが無力なことです。LinuxのブロックレイヤーはIOキューがIOリクエストでいっぱいになってしまうと、処理キューにバッチモードフラグを立て、処理のフェアネスよりもスループットを優先するため、しばらくの間、最後にIOをサブミットしたプロセスに優先的にIO発行権を与える機能があります。これがfsyncのケースでIO priorityを台無しにしてしまうのです。

 その場では、"slow fsync"のようなアドホックな解は好ましくなく、ioniceを真っ当にするという方向で合意を見たものの、具体的にどのように対応するかは今後の宿題となりました。

 これが契機となってPostgreSQLが性能アップしてくれたらいいですね。

Copyright © ITmedia, Inc. All Rights Reserved.

       | 次のページへ
ページトップに戻る