Linuxパフォーマンス最適化実践研究ノート

以下のコンテンツはオタクコースのものです。役立つ場合は、詳細コースのポスターをご覧ください。
画像名

CPUパフォーマンス

CPUパフォーマンスデバッグの一般的なコマンド

  1. mpstatビューのCPU使用率
# -P ALL 表示监控所有CPU,后面数字5表示间隔5秒后输出一组数据
$ mpstat -P ALL 5
Linux 4.15.0 (ubuntu) 09/22/18 _x86_64_ (2 CPU)
13:30:06 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
13:30:11 all 50.05 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 49.95
13:30:11 0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
13:30:11 1 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  1. 特定のプロセスのCPU使用率を表示するpidstat
# 间隔5秒后输出一组数据
$ pidstat -u 5 1
13:37:07      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
13:37:12        0      2962  100.00    0.00    0.00    0.00  100.00     1  stress
  1. プロセスのコンテキストスイッチpidstat-wを表示します。デフォルトでは、pidstatはプロセスのインジケーターデータを表示します。-tパラメーターを追加すると、スレッドのインジケーターが出力されます。
# 每隔5秒输出1组数据
$ pidstat -wt 5
Linux 4.15.0 (ubuntu) 09/23/18 _x86_64_ (2 CPU)
08:18:26 UID PID cswch/s nvcswch/s Command
08:18:31 0 1 0.20 0.00 systemd
08:18:31 0 8 5.40 0.00 rcu_sched

この結果には、私たちが焦点を当てている2列のコンテンツがあります。1つは1秒あたりの自発的なコンテキストスイッチの数を表すcswchであり、もう1つは1秒あたりの非自発的なコンテキストスイッチの数を表すnvcswchです。これらの2つの概念は、パフォーマンスの問題が異なるため、覚えておく必要があります。

  • いわゆる自発的なコンテキストスイッチとは、プロセスが必要なリソースを取得できないことによって引き起こされるコンテキストスイッチを指します。たとえば、I / Oやメモリなどのシステムリソースが不足している場合、自発的なコンテキスト切り替えが発生します。
  • 非自発的コンテキスト切り替えとは、タイムスライスの期限が切れたためにプロセスがシステムによって強制的にスケジュールされたときに発生するコンテキスト切り替えを指します。たとえば、多数のプロセスがCPUをめぐって競合している場合、不本意なコンテキスト切り替えが発生する傾向があります。
  1. vmstatを介してCPUコンテキストを表示し、キュー情報を実行するなど
# 每隔5秒输出1组数据
$ vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 
r b swpd free buff cache si so bi bo in cs us sy id wa st 
0 0 0 7005360 91564 818900 0 0 0 0 25 33 0 0 100 0 0

結果を一緒に見てみましょう。各列の意味を自分で解釈してみることができます。ここでは、特別な注意が必要な4つの列を強調します
。cs(コンテキストスイッチ)は、1秒あたりのコンテキストスイッチの数です。
in(interrupt)は、1秒あたりの割り込み数です。
r(実行中または実行可能)は、準備完了キューの長さ、つまり、実行中でCPUを待機しているプロセスの数です。
b(ブロック)は、中断できないスリープ状態にあるプロセスの数です。

  1. pstreeを介してプロセス間の関係を表示する
# -a 表示输出命令行选项
# p表PID
# s表示指定进程的父进程
$ pstree -aps 3084
systemd,1 
└─dockerd,15006 -H fd:// 
   └─docker-containe,15024 --config /var/run/docker/containerd/containerd.toml 
     └─docker-containe,3991 -namespace moby -workdir... 
       └─app,4009 
         └─(app,3084)

CPU関連の概念

1.平均負荷

平均負荷とは、システムが実行可能状態であり、単位時間あたりの中断不可能な状態にあるプロセスの平均数、つまりアクティブなプロセスの平均数を指します。妥当な平均負荷値をお勧めします。平均負荷がそうでない場合CPU数の70%以上

平均負荷とCPU使用率。負荷平均の意味に戻る必要があります。これは、単位時間あたりの実行可能な状態と中断できない状態のプロセスの数を指します。したがって、CPUを使用しているプロセスだけでなく、CPUを待機しているプロセスとI / Oを待機しているプロセスも含まれます。CPU使用率は、単位時間あたりのCPUビジー状態の統計であり、必ずしも平均負荷に対応しているわけではありません。といった:

  • 多くのCPUを使用する、CPUを集中的に使用するプロセスでは、平均負荷が増加します。現時点では、この2つは同じです。
  • I / Oを多用するプロセスは、I / Oを待機すると平均負荷も増加しますが、CPU使用率は必ずしも高くありません。
  • CPUを待機する多数のプロセススケジューリングも平均負荷の増加につながり、この時点でCPU使用率も比較的高くなります。

2.どのくらいのコンテキストスイッチが問題になりますか?

この値は、実際にはシステム自体のCPUパフォーマンスに依存します。私の意見では、システム内のコンテキストスイッチの数が比較的安定している場合、数百から1万以内であれば正常と見なす必要があります。ただし、コンテキストスイッチの数が10,000を超える場合、またはスイッチの数が桁違いに増える場合は、パフォーマンスの問題が発生している可能性があります。
このとき、コンテキストスイッチのタイプに基づいて特定の分析を行う必要もあります。例えば:

  • プロセスがリソースを待機していることを示す、より多くの自発的なコンテキストスイッチがあり、I / Oなどの他の問題が発生する可能性があります。
  • 非自発的なコンテキスト切り替えが増加し、プロセスがスケジュールを強制されていることを示しています。つまり、プロセスはすべてCPUをめぐって競合しており、CPUが実際にボトルネックになっていることを示しています。
  • 割り込みの数が増えており、CPUが割り込みハンドラーによって占有されていることを示しています。また、/ proc / interruptsファイルを表示して特定の割り込みタイプを分析する必要があります。

3.プロセスステータス?

  • RはRunningまたはRunnableの略語であり、プロセスがCPUの準備完了キューにあり、実行中または実行待ちであることを示します。
  • Dは、Disk Sleepの略語、つまりUninterruptible Sleepです。これは通常、プロセスがハードウェアと対話しており、対話プロセスが他のプロセスや割り込みによって中断されることを許可されていないことを意味します。
  • ZはZombieの略語で、「Plants vs. Zombies」というゲームをプレイしたことがある場合は、その意味を知っておく必要があります。これは、ゾンビプロセス、つまりプロセスが実際に終了したが、親プロセスがそのリソース(プロセス記述子、PIDなど)を再利用していないことを示します。
  • Sは、Interruptible Sleepの略語です。つまり、Interruptible Sleepは、プロセスがイベントを待機しているためにシステムによって中断されていることを意味します。プロセスが待機しているイベントが発生すると、プロセスは起動され、R状態になります。
  • IはIdleの略語で、アイドル状態であり、中断できないスリープカーネルスレッドで使用されます。前述のように、ハードウェアの相互作用によって引き起こされる中断のないプロセスはDで表されますが、一部のカーネルスレッドでは、実際には負荷がない場合があります。この状況を区別するためにアイドルが使用されます。D状態のプロセスは負荷平均を増加させますが、I状態のプロセスは増加させないことに注意してください。

4.CPU割り込み

Linuxの割り込みハンドラーは、上部と下部に分かれています。

  • 上半分はハードウェア割り込みに対応し、割り込みをすばやく処理するために使用されます。
  • 下半分はソフト割り込みに対応し、上半分の未完了の作業を非同期的に処理するために使用されます。
    Linuxのソフト割り込みには、ネットワークトランシーバ、タイミング、スケジューリング、RCUロックなど、さまざまなタイプがあります。/proc / softirqsを表示すると、ソフト割り込みの動作を確認できます。

5.CPU最適化の一般的なアイデア

アプリケーションの最適化
まず、アプリケーションの観点から、CPU使用率を削減する最善の方法は、もちろん、不要な作業をすべて排除し、コアロジックのみを保持することです。たとえば、ループのレベルを減らし、再帰を減らし、動的メモリ割り当てを減らします。さらに、アプリケーションのパフォーマンスの最適化には多くの方法も含まれています。ここに最も一般的な方法をリストしました。それらを書き留めることができます。

  • コンパイラーの最適化:多くのコンパイラーは最適化オプションを提供し、それらを適切にオンにします。コンパイル段階でコンパイラーからヘルプを取得して、パフォーマンスを向上させることができます。たとえば、gccは最適化オプション-O2を提供します。これは、アプリケーションコードがオンになった後に自動的に最適化します。
  • アルゴリズムの最適化:複雑度の低いアルゴリズムを使用すると、処理速度を大幅に高速化できます。たとえば、比較的大きなデータの場合、O(n ^ 2)ソートアルゴリズム(バブリング、挿入ソートなど)の代わりにO(nlogn)ソートアルゴリズム(高速ソート、マージソートなど)を使用できます。等。)。
  • 非同期処理:非同期処理を使用すると、特定のリソースを待機しているためにプログラムがブロックされるのを防ぐことができるため、プログラムの並行処理機能が向上します。たとえば、ポーリングをイベント通知に置き換えることで、CPUを消費するポーリングの問題を回避できます。マルチプロセスではなくマルチスレッド化:前述のように、プロセスコンテキストの切り替えと比較して、スレッドコンテキストの切り替えではプロセスのアドレス空間が切り替えられないため、コンテキストの切り替えのコストを削減できます。
  • キャッシュを有効に活用する:計算プロセスで頻繁にアクセスされるデータやステップをメモリにキャッシュできるため、次回メモリから直接取得して、プログラムの処理速度を上げることができます。

システムの最適化
システムの観点から、CPUの動作を最適化するには、一方ではCPUキャッシュの局所性を最大限に活用してキャッシュアクセスを高速化する必要があり、他方ではCPUを制御する必要があります。プロセスの使用法を使用し、プロセス間の相互作用を減らします。具体的には、システムレベルで多くのCPU最適化方法があります。ここでは、メモリと使用を容易にするための最も一般的な方法のいくつかもリストします。

  • CPUバインディング:プロセスを1つ以上のCPUにバインドすると、CPUキャッシュのヒット率が上がり、クロスCPUスケジューリングによって引き起こされるコンテキストスイッチングの問題を減らすことができます。
  • CPU排他的:CPUバインディングと同様に、CPUはさらにグループ化され、プロセスはCPUアフィニティメカニズムを介してCPUに割り当てられます。このように、これらのCPUは指定されたプロセスによって排他的に占有されます。つまり、他のプロセスはこれらのCPUを使用できません。
  • 優先度の調整:niceを使用してプロセスの優先度を調整します。正の値は優先度を下げ、負の値は優先度を上げます。優先度の数値的な意味については前述しましたが、忘れた場合は時間内に確認してください。ここで、非コアアプリケーションの優先度を適切に下げ、コアアプリケーションの優先度を上げると、コアアプリケーションが最初に処理されるようになります。
  • プロセスのリソース制限を設定する:Linux cgroupsを使用して、プロセスのCPU使用率の上限を設定します。これにより、アプリケーション自体の問題によるシステムリソースの枯渇を防ぐことができます。
  • NUMA(Non-Uniform Memory Access)の最適化:NUMAをサポートするプロセッサは複数のノードに分割され、各ノードには独自のローカルメモリスペースがあります。NUMA最適化は、実際には、CPUが可能な限りローカルメモリにのみアクセスできるようにすることです。
  • 割り込み負荷分散:ソフト割り込みであろうとハード割り込みであろうと、それらの割り込みハンドラーは多くのCPUを消費する可能性があります。irqbalanceサービスをオンにするか、smp_affinityを構成して、割り込み処理プロセスを複数のCPUに自動的に負荷分散します。

メモリパフォーマンス

メモリ関連のコマンドを表示する

  1. キャッシュヒット率cachestatを表示する
$ cachestat 1 3 
TOTAL MISSES HITS DIRTIES BUFFERS_MB CACHED_MB 
2 0 2 1 17 279 
2 0 2 1 17 279 
2 0 2 1 17 279
  • 合計、I / Oの総数は言った。
  • MISSES、キャッシュミスの数を示します。
  • HITS、これはキャッシュヒットの数を意味します。
  • DIRTIESは、キャッシュに追加されたダーティページの数を表します。BUFFERS_MBは、バッファのサイズをMB単位で表し、CACHED_MBは、キャッシュのサイズをMB単位で表します。
  1. プロセスキャッシュのヒット率cachetopを表示する
$ cachetop
11:58:50 Buffers MB: 258 / Cached MB: 347 / Sort: HITS / Order: ascending
PID      UID      CMD              HITS     MISSES   DIRTIES  READ_HIT%  WRITE_HIT%
   13029 root     python                  1        0        0     100.0%       0.0%

メモリ関連の概念

1.Linuxメモリはどのように機能しますか

各プロセスのアドレス空間にはカーネル空間が含まれていますが、これらのカーネル空間は実際には同じ物理メモリに関連付けられています。

もちろん、システムはプロセスがすべてのメモリを使い果たすことを許可しません。メモリが不足していることが判明すると、システムは次の3つの方法などの一連のメカニズムを通じてメモリを再利用します。

  • LRU(最近使用されていない)アルゴリズムを使用して最も使用頻度の低いメモリページを再利用するなど、キャッシュを再利用します。
  • 頻繁にアクセスされないメモリを再利用し、頻繁に使用されないメモリをスワップパーティションを介してディスクに直接書き込みます。
  • プロセスを強制終了します。メモリが不足すると、システムはOOM(メモリ不足)を使用して、大量のメモリを消費するプロセスを直接強制終了します。プロセスが消費するメモリが多いほど、oom_scoreは大きくなり、プロセスが消費するCPUが多いほど、oom_scoreは小さくなります。

プロセスがmalloc()を介してメモリに適用される場合、メモリはすぐには割り当てられませんが、初めてアクセスされると、ページフォールト例外を介してカーネルにメモリが割り当てられます。
詳細なメモリテスト:https://blog.holbertonschool.com/hack-the-virtual-memory-malloc-the-heap-the-program-break/

2.バッファとキャッシュ

cache = Cached + SReclaimable

  • バッファは、ディスクデータをキャッシュするために使用される元のディスクブロックの一時的なストレージであり、通常はそれほど大きくありません(約20MB)。このようにして、カーネルは分散書き込みを集中させ、ディスク書き込みを均一に最適化できます。たとえば、複数の小さな書き込みを1つの大きな書き込みにマージすることができます。
  • キャッシュは、ディスクからファイルを読み取るページキャッシュです。つまり、ファイルから読み取られたデータをキャッシュするために使用されます。このようにして、次にこれらのファイルデータにアクセスするときに、低速のディスクに再度アクセスすることなく、メモリから直接データをすばやく取得できます。
  • SReclaimableはスラブの一部です。スラブは2つの部分で構成され、再生可能な部分はSReclaimableで記録され、再生不可能な部分はSUnreclaimで記録されます。

バッファはディスクデータのキャッシュであり、キャッシュはファイルデータのキャッシュであり、読み取り要求と書き込み要求の両方で使用されます。

3.メモリ分析

2番目の例では、それを解放してシステムの使用可能なメモリが不足していることがわかった場合、最初にメモリがキャッシュ/バッファによって占有されているかどうかを確認します。キャッシュ/バッファを除外した後も、引き続きpidstatまたはtopを使用して、最も多くのメモリを占有しているプロセスを見つけることができます。プロセスを特定したら、プロセスメモリスペースツール(pmapなど)を使用して、プロセスアドレススペースのメモリ使用量を分析します。

4.いくつかの一般的な最適化のアイデアがあります

  • スワップを禁止するのが最善です。スワップを有効にする必要がある場合は、swappinessの値を減らして、メモリ回復中にスワップを使用する傾向を減らします。
  • メモリの動的割り当てを減らします。たとえば、メモリ割り当ての代わりに配列を使用すると、メモリプール、巨大なページ(HugePage)などを使用できます。
  • キャッシュとバッファを使用してデータにアクセスしてみてください。たとえば、スタックを使用して、キャッシュする必要のあるデータを格納するためのメモリスペースを明示的に宣言したり、Redisなどの外部キャッシュコンポーネントを使用してデータアクセスを最適化したりできます。
  • cgroupsおよびその他の方法を使用して、プロセスのメモリ使用量を制限します。このようにして、異常なプロセスによってシステムメモリが使い果たされないようにすることができます。
  • / proc / pid / oom_adjを使用してコアアプリケーションのoom_scoreを調整します。このようにして、メモリが不足している場合でも、コアアプリケーションがOOMによって強制終了されないことが保証されます。

5.ファイルシステムとディスクの違い

  • 通常のファイルを読み書きする場合、I / O要求は最初にファイルシステムを通過し、次にファイルシステムがディスクとの対話を担当します。
  • ブロックデバイスファイルの読み取りと書き込みを行う場合、ファイルシステムはスキップされ、ディスクと直接対話します。これは、いわゆる「raw I / O」です。
    これらの2つの読み取り方法と書き込み方法で使用されるキャッシュは当然異なります。ファイルシステムによって管理されるキャッシュは、実際にはキャッシュの一部です。rawディスクキャッシュはBufferを使用します。

おすすめ

転載: blog.csdn.net/zimu312500/article/details/113871150