web-dev-qa-db-ja.com

キャッシュを継続的にドロップしない限り、Linuxシステムが途切れるのはなぜですか?

過去数か月間、Linuxシステムで非常に苛立たしい問題が発生しました。Firefoxのオーディオ再生やマウスの動きなどで途切れ、数秒ごとにわずか1秒未満(ただし目立つ)のスタッターが発生します。この問題は、メモリキャッシュがいっぱいになるか、ディスク/メモリを大量に消費するプログラム(バックアップソフトウェアresticなど)を実行しているときに悪化します。ただし、キャッシュがいっぱいでない場合(たとえば、非常に軽い負荷の場合)、すべてが非常にスムーズに実行されます。

perf topの出力を見ると、これらのラグの期間中、list_lru_count_oneのオーバーヘッドが高い(〜20%)ことがわかります。 htopは、50〜90%のCPUを使用するkswapd0も示しています(ただし、影響はそれよりはるかに大きいように感じます)。極端な遅延の時間帯には、htopCPUメーターはカーネルのCPU使用率によって支配されることがよくあります。

私が見つけた唯一の回避策は、カーネルに空きメモリ(sysctl -w vm.min_free_kbytes=1024000)を保持させるか、echo 3 > /proc/sys/vm/drop_cachesを介してメモリキャッシュを継続的に削除することです。もちろん、どちらも理想的ではなく、吃音を完全に解決するものでもありません。頻度が減るだけです。

なぜこれが起こっているのかについて誰かが何か考えを持っていますか?

システム情報

  • 20 GBの(不一致の)DDR3RAMを搭載したi7-4820k
  • Linux4.14-4.18のNixOS不安定版で再現
  • DockerコンテナとKubernetesをバックグラウンドで実行します(マイクロスタッターを作成するべきではないと思いますか?)

私がすでに試したこと

  • マルチキューI/Oスケジューラーを使用したI/Oスケジューラー(bfq)の変更
  • ConKolivasによる-ckパッチセットの使用(役に立たなかった)
  • Zramを使用して、スワップを無効にし、swappinessを変更します

[〜#〜] edit [〜#〜]:わかりやすくするために、htopperfの写真を次に示します。そのようなラグスパイクの間に。高いlist_lru_count_oneCPU負荷とkswapd0 +高いカーネルCPU使用率に注意してください。

htop and perf output

6
Pneumaticat

問題が見つかりました!

コンテナ/メモリcgroupが多数ある場合、Linuxのメモリリクレーマのパフォーマンスの問題であることが判明しました。 (免責事項:私の説明には欠陥がある可能性があります。私はカーネル開発者ではありません。)この問題は4.19-rc1 +で修正されました このパッチセット

このパッチセットは、多くのシュリンクとメモリcgroupを備えた(つまり、多くのコンテナを備えた)マシンで発生するshrink_slab()が遅いという問題を解決します。問題は、shrink_slab()の複雑さがO(n ^ 2)であり、コンテナー数の増加に伴って急速に増加することです。

200個のコンテナーがあり、すべてのコンテナーに10個のマウントと10個のcgroupがあるとします。すべてのコンテナタスクは分離されており、外部コンテナのマウントには触れません。

グローバルリクレイムの場合、タスクはmemcgs全体を反復処理し、すべてのmemcg対応シュリンクを呼び出す必要があります。つまり、タスクはmemcgごとに200 * 10 = 2000のシュリンクを訪問する必要があり、2000 memcgsがあるため、do_shrink_slab()の合計呼び出しは2000 * 2000 = 4000000になります。

かなりの数のコンテナーを実行しているため、システムが特に大きな打撃を受けました。これが問題の原因である可能性があります。

同様の問題に直面している人に役立つ場合のトラブルシューティング手順:

  1. コンピューターが途切れるときにkswapd0が大量のCPUを使用していることに注意してください
  2. Dockerコンテナを停止し、メモリを再度いっぱいにしてみてください→コンピュータが途切れません!
  3. ftrace(以下 Julia Evanのすばらしい説明ブログ )を実行してトレースを取得します。kswapd0shrink_slabsuper_cache_countでスタックする傾向があることを確認してください。 、およびlist_lru_count_one
  4. Google shrink_slab lru slow、パッチセットを見つけてください!
  5. Linux 4.19-rc3に切り替えて、問題が修正されていることを確認します。
3
Pneumaticat

私が最初に提案したであろう多くのこと(スワップ構成の調整、I/Oスケジューラーの変更など)をすでに試したようです。

すでに変更を試みたものとは別に、VMライトバック動作のやや脳死したデフォルトを変更することを検討することをお勧めします。これは、次の6つのsysctl値によって管理されます。

  • vm.dirty_ratio:ライトバックがトリガーされる前に、ライトバックを保留する必要がある書き込みの量を制御します。フォアグラウンド(プロセスごと)のライトバックを処理し、RAMの整数パーセントとして表されます。デフォルトはRAMの10%
  • vm.dirty_background_ratio:ライトバックがトリガーされる前に、ライトバックを保留する必要がある書き込みの量を制御します。バックグラウンド(システム全体)のライトバックを処理し、RAMの整数パーセントとして表されます。デフォルトはRAMの20%
  • vm.dirty_bytes:合計バイト数で表されることを除いて、vm.dirty_ratioと同じです。このまたはvm.dirty_ratioのいずれか、最後に書き込まれた方が使用されます。
  • vm.dirty_background_bytes:合計バイト数で表されることを除いて、vm.dirty_background_ratioと同じです。このまたはvm.dirty_background_ratioのいずれか、最後に書き込まれた方が使用されます。
  • vm.dirty_expire_centisecs:上記の4つのsysctl値がまだトリガーしていない場合に、保留中のライトバックが開始するまでに100分の1秒が経過する必要があります。デフォルトは100(1秒)です。
  • vm.dirty_writeback_centisecs:カーネルがダーティページのライトバックを評価する頻度(100分の1秒単位)。デフォルトは10(10分の1秒)です。

したがって、デフォルト値では、10分の1秒ごとに、カーネルは次のことを行います。

  • 最後に変更されたページが1秒以上前の場合は、変更されたページを永続ストレージに書き出します。
  • 書き出されていない変更されたメモリの合計量がRAMの10%を超える場合は、プロセスの変更されたすべてのページを書き出します。
  • 書き出されていない変更されたメモリの合計量がRAMの20%を超える場合は、システム内の変更されたすべてのページを書き出します。

したがって、システムが最大4ギガバイトを書き出そうとしている可能性があるため、デフォルト値が問題を引き起こしている理由を簡単に理解できるはずです。 )データの永続ストレージへの10分の1秒ごと。

最近の一般的なコンセンサスは、vm.dirty_ratioをRAMの1%に調整し、vm.dirty_background_ratioを2%に調整することです。これは、約64GB未満のシステムの場合RAMその結果、当初の意図と同等の動作が得られます。

調べるべき他のいくつかの事柄:

  • vm.vfs_cache_pressuresysctlを少し増やしてみてください。これは、RAMが必要なときにカーネルがファイルシステムキャッシュからメモリをどれだけ積極的に再利用するかを制御します。デフォルトは100ですが、50未満に下げないでください(OOM条件を含め、50未満にすると、非常に悪い動作になります)、そして、それを約200をはるかに超えて上げないでください(はるかに高くなると、カーネルは実際にはできないメモリを再利用しようとして時間を浪費します)。適度に高速なストレージがある場合は、150まで上げると、実際に応答性が目に見えて向上することがわかりました。
  • メモリオーバーコミットモードを変更してみてください。これは、vm.overcommit_memorysysctlの値を変更することで実行できます。デフォルトでは、カーネルはヒューリスティックアプローチを使用して、実際にコミットできるRAM)の量を予測しようとします。これを1に設定すると、ヒューリスティックが無効になり、カーネルに無限大のように動作するように指示されます。これを2に設定すると、カーネルは、システム上のスワップスペースの合計量に実際のRAM(vm.overcommit_ratioによって制御される)のパーセンテージを加えたものより多くのメモリにコミットしないようになります。
  • vm.page-clustersysctlを微調整してみてください。これは、一度にスワップインまたはスワップアウトされるページ数を制御します(これは基数2の対数値であるため、デフォルトの3は8ページに変換されます)。実際にスワップしている場合、これはページのスワップインとスワップアウトのパフォーマンスを向上させるのに役立ちます。
3