私が最初に提案した多くのこと (スワップ構成の微調整、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
これは、RAM が約 64GB 未満のシステムでは、当初の意図と同等の動作になります。
その他の調査事項:
vm.vfs_cache_pressure
を増やしてみてください 少しsysctl。これは、RAM が必要なときに、カーネルがファイルシステム キャッシュからメモリをどれだけ積極的に再利用するかを制御します。デフォルトは 100 です。50 未満に下げないでください ( OOM 条件を含めて 50 を下回ると、非常に悪い動作になります)、約 200 をはるかに超えないようにします (これをはるかに超えると、カーネルは実際にはできないメモリを再利用しようとして時間を浪費します)。適度に高速なストレージを使用している場合、150 まで上げると実際に応答性が目に見えて改善されることがわかりました。- メモリのオーバーコミット モードを変更してみてください。これは、
vm.overcommit_memory
の値を変更することで実行できます。 sysctl.デフォルトでは、カーネルはヒューリスティックなアプローチを使用して、実際にコミットできる RAM の量を予測しようとします。これを 1 に設定すると、ヒューリスティックが無効になり、カーネルが無限のメモリを持っているかのように動作するように指示されます。これを 2 に設定すると、カーネルは、システム上のスワップ領域の合計量に実際の RAM の割合 (vm.overcommit_ratio
によって制御) を加えた量よりも多くのメモリをコミットしないように指示されます。 ). vm.page-cluster
を微調整してみてください sysctl.これは、一度にスワップ インまたはスワップ アウトされるページ数を制御します (2 を底とする対数値であるため、デフォルトの 3 は 8 ページに変換されます)。実際にスワップする場合、これにより、ページのスワップ インとスワップ アウトのパフォーマンスが向上します。
問題が見つかりました!
多数のコンテナ/メモリ cgroup がある場合、Linux のメモリ リクレーマのパフォーマンスの問題であることが判明しました。 (免責事項:私の説明には誤りがあるかもしれません。私はカーネル開発者ではありません。) この問題は、このパッチ セットの 4.19-rc1+ で修正されています:
<ブロック引用>このパッチセットは、多くのシュリンクとメモリー cgroup を持つ (つまり、多くのコンテナーを持つ) マシンで発生する、shrink_slab() が遅いという問題を解決します。問題は、shrink_slab() の複雑さが O(n^2) であり、コンテナ数の増加に伴って急速に増大することです。
200 個のコンテナーがあり、すべてのコンテナーに 10 個のマウントと 10 個の cgroup があるとします。すべてのコンテナ タスクは分離されており、外部コンテナ マウントには影響しません。
グローバルな回収の場合、タスクはすべての memcg を反復処理し、それらすべてに対してすべての memcg 対応シュリンカーを呼び出す必要があります。つまり、タスクは memcg ごとに 200 * 10 =2000 のシュリンクを訪問する必要があり、2000 個の memcg があるため、do_shrink_slab() の呼び出しの合計は 2000 * 2000 =4000000 になります。
かなりの数のコンテナーを実行しているため、私のシステムは特に大きな打撃を受けました。これが問題の原因であった可能性があります。
同様の問題に直面している人に役立つ場合に備えて、私のトラブルシューティング手順:
<オール>kswapd0
コンピューターがカクカクするときに大量の CPU を使用するftrace
を実行 (Julia Evan の壮大な説明ブログに従って) トレースを取得するには、その kswapd0
を参照してください shrink_slab
でスタックする傾向があります 、 super_cache_count
、および list_lru_count_one
.shrink_slab lru slow
、パッチセットを見つけてください!