えいのうにっき

a-knowの日記です

読書メモ・詳解システムパフォーマンス 第6章/CPU

「詳解システムパフォーマンス」の読書メモシリーズ・第5弾。

詳解 システム・パフォーマンス

詳解 システム・パフォーマンス

感想

  • おもしろかった。やはりここでも、いかに自分が雰囲気で「CPU」というものを捉えていたか、を痛感した。
  • 特にハードウェアよりの話(インターコネクトとか)はちんぷんかんぷん、という感じ。
  • 色んなツールを使っての分析やプロファイリング、チューニング、実践してみたいという気持ちはあるが腰が重い。
  • LAとか、Mackerel でみる Linux システムメトリック項目の見方・考え方 - えいのうにっき でさらっと書いたような部分は再確認できて、それもよかった。

読書メモ

6.1 用語

  • プロセッサ
    • システムやプロセッサボードのソケットに装着される物理チップ。
    • コア、ハードウェアスレッドとして実装されたひとつ以上の CPU を含む。
  • コア
    • マルチコアプロセッサに含まれる、独立した CPU インスタンスのこと。
  • ハードウェアスレッド
  • 論理 CPU
    • オペレーティングシステムの CPU インスタンス、スケジューリングできる CPU エンティティ。
    • プロセッサは、ハードウェアスレッド・コア・シングルコアプロセッサのいずれかで論理 CPU を実装する。

6.2モデル

6.2.1

4個のコアを搭載し、8個のハードウェアスレッドを持つシングルプロセッサという構成の CPU の場合、それは OS から見ると、

  • 個々のハードウェアスレッドは1個の論理CPUに見える
  • 全体では8個のCPUに見える

6.2.2 CPU のメモリキャッシュ

プロセッサは、メモリI/Oのパフォーマンスを向上させるためにさまざまなハードウェアキャッシュを持っている。 CPU レジスタ / レベル1キャッシュ / レベル2キャッシュ / レベル3キャッシュ。以降は メインメモリ / ストレージデバイス となる。

6.2.3 CPU のランキュー

  • 実行可能な状態でランキューにキューイングされているソフトウェアスレッドの数は、CPUの飽和を示す重要なパフォーマンス指標となる。
    • この待ち時間をスケジューラレイテンシと呼ぶ。
  • マルチプロセッサシステムでは、カーネルは個々のCPUにランキューを提供し、スレッドを同じランキューにキューイングし続けようとする。
    • CPU はスレッドのデータをキャッシングしているため。
    • この特性をCPUアフィニティと呼ぶ。

6.3. コンセプト

6.3.1 クロックスピード

  • 個々の CPU 命令は、実行のためにひとつ以上のクロックサイクルを必要とする。

6.3.2 命令

  • CPUは命令セットから選ばれた命令を実行する。命令の実行には以下のステップが含まれる。
    1. 命令のフェッチ
    2. 命のデコード
    3. 命令の実行
    4. メモリアクセス(オプション・命令によっては無い)
    5. レジスタへの書き戻し(オプション・命令によっては無い)
  • 各ステップはその実行のために少なくとも1クロックサイクルを必要とするが、メインメモリの読み書きには数十サイクル必要なので、このステップが最も遅い。
    • その間の命令の実行はストールされ、止まっている。これを削減するためにCPUキャッシングが存在している
    • ストール中のサイクルはストールサイクルと呼ぶ。

6.3.3 命令パイプライン

6.3.4 命令幅

  • 同じタイプの複数の機能ユニットをまとめて、クロックサイクルごとにより多くの命令を先にすすめる CPU アーキテクチャがあり、これをスーパースカラーと呼ぶ。
  • 並列処理する命令の数のことを命令幅という。

6.3.5 CPI, IPC

  • CPI : Cycles Per Instruction。命令のコストの大きさを示す指標。
    • 命令処理の効率性を示す指標であり、命令自体の効率性を示すものではない。
    • これが高いということは、CPU がストールしていることが多いということ。
    • CPIが高い場合にクロックスピードの速い CPU を搭載しても、CPU はメモリ I/O の完了を待つために同じ時間だけ待たなければならない(ストールサイクルばかりが増える)ので、パフォーマンス改善にはつながらない場合がある。
  • IPC : Instructions Per Cycle。1サイクルあたりに処理されている命令数。
  • これらの値は、既知のワークロードを実行して実験的に判断する。

6.3.6 使用率

  • 一定期間内で CPU インスタンスが仕事をしていてビジー状態(ユーザーレベルアプリケーションスレッドまたはその他のカーネルスレッドを実行している状態、もしくは割り込みを処理している状態)になっている時間の割合を%で表現したもの。
  • CPUの使用率が高いのはかならずしも問題ではない。CPU使用率をROIインジケータと考えることもできる。
  • 他のリソースタイプとは異なり、使用率が高くなっても、カーネルが優先度・プリエンプション・タイムシェアリングをサポートしているため、パフォーマンスはかならずしも大きく下がるとは限らない。
    • これら全てを考慮した上で優先度の高いものの高速実行を、カーネルは保障する。
  • CPU使用率の測定値としては、メモリストールサイクルを含む適切なアクティビティのためにクロックサイクルが使われているすべての時間が用いられる

6.3.7 ユーザー時間/カーネル時間

  • システム全体で計測すると、ユーザー時間/カーネル時間の割合は、実行されているワークロードのタイプを表すものとなる。
  • CPUを酷使するアプリケーションは、ほとんどの時間をユーザーレベルコードの実行に費やし、ユーザー時間:カーネル時間が99:1ほどにもなる。
  • I/Oを酷使するアプリケーションは、I/Oを実行するカーネルコードを呼び出すシステムコールの割合が高くなり、例えば70:30くらいになる。

6.3.8 飽和

  • 使用率100%のCPUは飽和しており、スケジューラレイテンシの影響を受けて、全体としてのパフォーマンスは下がる。
  • CPUの飽和には、クラウドのマルチテナント環境などで設定されるCPUリソースコントロールによるものもある。
    • CPUの使用率が100%にならなくても、設定された限界に達すると、同じく飽和と似たような状態となる。

6.3.9 プリエンプション

優先度の高いスレッドが、現在実行されているスレッドからCPUを奪い、自分の実行を開始できること。

6.3.10 優先度の逆転

  • 優先度の低いスレッドがリソースを抱え込み、優先度の高いスレッドの実行をブロックすると、優先度の逆転が起きる。
  • Solaris ベースのカーネルは、これを防ぐために優先度の継承を実装している

6.3.11 マルチプロセスとマルチスレッディング

  • ひとつのアプリケーションで複数のCPUを利用するためには、実行スレッドを分割して並列実行できるようにしなければならない。
  • 複数のCPUに対応できるようにアプリケーションをスケーリングするためのテクニックには、マルチプロセスとマルチスレッディングのふたつがある。
  • マルチプロセス
    • fork()を使う。
    • プロセスごとにアドレス空間が別々になる分、メモリオーバーヘッドは大きい
    • CPUオーバーヘッドも、fork()やexit()のコストに加え、MMUの仕事も含まれる
    • 通信はIPC経由で行なう。ふたつのアドレス空間のあいででデータを移動するためのコンテキストスイッチが発生する
    • 各プロセスがexit()を呼び出すことが可能で、そのときにすべてのメモリがシステムに返される
  • マルチスレッディング
    • スレッドAPIを用いることで生成可能。
    • スタックとレジスタの空間が増えるだけなので、メモリオーバーヘッドは小さい。
    • API呼び出しにより生成できるのでCPUオーバーヘッドも小さい
    • 共有メモリに直接できるため、スレッド間でのやりとりも高速。同期プリミティブによってデータの完全性を保障する必要がある。
    • 複数のスレッド間でCPUの競合が発生したり、メモリを再利用するときにフラグメンテーションが起きたりすることがある

6.3.12 ワードサイズ

  • プロセッサは、最大のワードサイズ(32bit / 64bit)をもとに設計されている
  • このサイズが整数のサイズ、レジスタのサイズになる
  • ワードサイズは一般にアドレス空間のサイズやデータバスの幅としても使われている
  • サイズが大きい方がパフォーマンスは良くなり得るが、データ型によっては、未使用ビットの分、オーバーヘッドがかかることもある。
  • プロセッサとオペレーティングシステムは複数のワードサイズをサポートでき、異なるワードサイズをを対象としてコンパイルしたアプリケーションを同時に実行できる。

6.3.13 コンパイラの最適化

  • アプリケーションのCPU実行時間は、コンパイラのオプションと最適化によって大幅に短縮できる。
  • 新しいコンパイラを使うだけで大幅に向上することもある

6.4 アーキテクチャ

6.4.1 ハードウェア

  • CPUキャッシュ
    • さまざまなハードウェアキャッシュは、通常、プロセッサに搭載されているか、プロセッサとともに並べられているかのどちらか。
    • レベル1キャッシュのアクセス時間は一般に数CPUクロックサイクル。レベル2キャッシュになると10クロックサイクル前後。
    • キャッシュ内の新しいエントリを探すときの制約を示すキャッシュ特性のことを、連想性と呼ぶ。以下のようなタイプがある。
      • 完全連想・フルアソシエイティブ:キャッシュはどこの新エントリでも見つけられる。
      • 直接マップ・ダイレクトマップ:各エントリは、キャッシュ内に有効な位置をひとつしか持っていない。
      • 群連想・セットアソシテイティブ:マッピングによりキャッシュのサブセットが識別され、そのサブセットのなかでは他のアルゴリズムが実行される。よく用いられる方式。
    • キャッシュにデータを格納するとき、必ずある単位(x86 プロセッサの典型的なサイズは64バイト)ごとに書き込みが行われる。その単位のことをキャッシュラインと呼ぶ。コンパイラは、パフォーマンスを最適化するときにキャッシュラインサイズを考慮にいれる。
    • キャッシュコヒーレンシ:メモリは、同時に複数のプロセッサの複数のCPUキャッシュにキャッシングされることがある。あるCPUがそのメモリに変更を加えたら、全てのキャッシュは、次の読み出しでは新しく書き換えられたコピーを取得するようにしなければならない。
    • MMUでの仮想アドレスから物理アドレスへの変換は、まずオンチップTLBを使ってキャッシュアドレス変換を行なう。
      • キャッシュミスを起こしたときには、MMUが直接読み出せるページテーブル(メインメモリ内の変換テーブル)を使う。
      • 新しいプロセッサではTLBミスをハードウェア内で処理できるようになり、従来までのコストが大幅に削減された。
    • マルチプロセッサアーキテクチャでは、各プロセッサは共有システムバスか専用インターコネクトを使って接続される。
      • システムバスを使う方法では、プロセッサの数が増えると共有バスリソースに対する競合のためにスケーラビリティの問題が起きる。
      • 最近では一般に NUMA のマルチプロセッサで、システムバスではなく CPU インターコネクトを使っている。
      • インターコネクトは I/O コントローラなどのプロセッサ以外のコンポーネントも接続できる。システム全体のボトルネックにならないように高帯域幅に設計されている。
  • CPUパフォーマンスカウンタ
    • 低水準CPUアクティビティを数えるようにプログラムすることができるプロセッサレジスタ。一般に、以下のもののカウンタが含まれている。
      • CPUサイクル
      • CPU命令
      • レベル1,2,3キャッシュアクセス
      • 浮動小数点演算ユニット
      • メモリI/O
      • リソースI/O
    • 個々のCPUも、イベントを記録するようプログラムできる少数のレジスタを持っている。

6.4.2 ソフトウェア

  • スケジューラ:カーネルの CPU スケジューラの主要機能は以下。
    • タイムシェアリング:実行可能スレッドの間のマルチタスキング。
    • プリエンプション
    • ロードバランシング:アイドル状態、それほどビジーではない状態のCPUのランキューに実行可能スレッドを移す。
      • 同じ優先度のスレッドの中でどれを実行すべきかをスケジューラが簡単に管理できるよう、優先度ごとのランキューもある。
  • スケジューリングタスク:実行可能スレッドのふるまいを管理するものとして、スケジューリングクラスがある。例えば以下のようなものを管理している。
    • 実行可能スレッドの優先度
      • ユーザー定義のナイス値の影響を受ける。
    • CPU上の時間がタイムスライスされているかどうか
    • タイムスライスの量
  • アイドルスレッド:実行可能スレッドがないときにCPUは「なにもしていない」わけではなく、カーネルの「アイドルスレッド(またはアイドルタスク)」を実行している。
  • NUMAグループ:NUMAシステムのパフォーマンスは、カーネルにNUMAを意識させ、NUMAに合わせてスケジューリングやメモリの配置を適切な方法にできるようにすれば、大幅に向上させられる。

6.5 メソドロジ

6.5.1 ツールメソッド

CPUの場合、ツールメソッドでチェックできるのは以下のようなことである。

  • uptime
  • vmstat
    • 1秒間隔で実行し、アイドル欄をチェックすれば、どれぐらいの余裕があるかがわかる。
  • mpstat
    • 個別のビジーなCPUをチェックし、スレッドのスケーラビリティ問題になっている可能性のあるものを見極める。
  • top prstat
    • どのプロセス、ユーザーがCPUをもっとも消費しているかを表示する。
  • pidstat prstat
    • CPUをもっとも消費しているプロセスをユーザー時間とシステム時間に分けて表示する。
  • perf dtrace stap oprofile
  • perf cpustat
    • CPIを計測する。

6.5.2 USEメソッド

パフォーマンス問題調査の初期段階で、すべてのコンポーネントを対象としてボトルネックやエラーを見つけるためのメソドロジ。 個々のCPUについて、以下のような情報をチェックする。

  • 使用率
    • CPUがビジーだった(アイドルスレッド以外を実行していた)時間
  • 飽和
    • 実行可能スレッドがCPU待ちでキューイングされている度合い
    • ロードアベレージの一部として提供されている
  • エラー
    • 修正可能なものも含むCPUエラー
    • 一部のプロセッサとオペレーティングシステムは、修正可能なエラーの増加を検知してCPUをオフラインにするものもある

6.5.3 ワークロードの特性の把握

目的は、得られたパフォーマンスではなく、かかった負荷の特性を明らかにすること。 CPUワークロードを特徴づける基本属性としては、次のものがある。

ワークロードの特性を把握するためのチェックリストとして、以下のようなものがある。

  • システム全体でCPUの使用率はどうなっているか。また、CPUごとではどうか。
  • CPUの負荷はどれくらい並列化されているか。シングルスレッドか。スレッドはいくつか。
  • どのアプリケーション、またはユーザーがCPUをつかっているか。それはどのくらいか。
  • どのカーネルスレッドがCPUを使っているか。それはどのくらいか。
  • 割り込みのCPU使用状況はどれくらいか。
  • CPUインターコネクトの使用率はどれくらいか。
  • CPUはなぜ使われているか。ユーザー/カーネルレベルのコールパスはどうか。
  • どのようなタイプのストールサイクルが発生しているか。

6.5.4 プロファイリング

以下の手順に従い、一定のインターバルでCPUの状態をサンプリングするとプロファイリングできる。

  1. 選択
    • キャプチャするプロファイルデータのタイプとキャプチャの頻度を選択する。
  2. 開始
    • 一定のインターバルでサンプリングを開始する
    • サンプリングと何らかのアクティビティとの歩調が合ってしまわないような頻度とすることを心がける
  3. 待機
    • 関心を持っているアクティビティの発生を待つ
  4. 終了
    • サンプリングを終了し、サンプルデータを集める
  5. 処理
    • データを処理する

CPUプロファイルデータは、次の要素を基礎としたものになる。

ユーザーレベルかカーネルレベルのどちらかで部分的なスタックを取り出すか、実行している関数名だけを取り出せば、少ないデータでCPUの使用状況を十分に明らかにできる場合がある。 キャッシュやインターコネクトなど、CPUリソースの特定の部分の使用状況を知りたい場合は、インターバルではなくCPCベースのイベントトリガを使ってプロファイリングするとよい。

6.5.5 サイクル分析

CPC(CPU Performance Counter)を使えば、CPUの使用率がサイクルレベルでわかる。サイクルがレベル1,2,3キャッシュミス、メモリI/O、リソースI/Oでストールしているか、浮動小数点演算その他のアクティビティで使われているのかがわかる。 サイクル分析はCPIの計測から始める。

  • CPIが高い
    • ストールサイクルのタイプを調査する
  • CPIが低い
    • 実行される命令数を減らす方法をコード内で探す

CPC は、カウンタの値を計測することとは別に、特定の値がオーバーフローしたときにカーネルに割り込むように設定することもできる。

6.5.6 パフォーマンスモニタリング

現にある問題や経時的なふるまいのパターンを明らかにすることができる。CPUの主要な指標は以下。

  • 使用率
    • CPUごとにモニタリングすべき項目。
  • 飽和
    • ロードアベレージから推定できるランキューの長さか、スレッドスケジューラレイテンシの計測値

6.5.7 静的パフォーマンスチューニング

  • 何個のCPUが使える状態になっているか。それはコアか、ハードウェアスレッドか。
  • CPUのアーキテクチャはシングルプロセッサかマルチプロセッサか。
  • CPUキャッシュのサイズはどれだけか。供給されているか。
  • CPUのクロックスピードはどれだけか。動的か。動的なスピード変更はBIOSでも有効になっているか。
  • BIOSで有効、無効になっているCPU関連の機能は何か。
  • 対象のプロセッサモデルには、パフォーマンス問題があるか。
  • 対象のBIOSファームウェアバージョンにはパフォーマンス問題があるか。
  • ソフトウェアで強制されたCPUの使用制限はあるか。あるならどのようなものか。

6.5.8 優先度のチューニング

  • ナイス値の設定
  • スケジューリングクラスやスケジューラポリシーの変更
  • クラスのチューニングの変更

6.5.9 リソースコントロール

6.5.10 CPUのバインド

個別のCPU、またはCPUのコレクションにプロセスやスレッドをバインドすることもできる。こうすると、プロセスのCPUキャッシュのウォーム度が上がり、メモリI/Oのパフォーマンスが上がる。 一般的に、バインドにはふたつの方法がある。

  • プロセスのバインド
  • 排他的CPUセット
    • 割り当てられたプロセス以外は使えないようにCPUセットをパーティション化する。
    • プロセスがアイドル状態でもほかのプロセスはCPUを使えず、キャッシュのウォーム度が損なわれないため、CPUキャッシュのヒット率も上がる

6.5.11 マイクロベンチマーキング

CPUのマイクロベンチマーキングのためにはさまざまなツールが作られているが、それらは単純なオペレーションを何度も実行するために必要な時間を計測する。 CPUのマイクロベンチマーキングにより計測されるオペレーションには次のようなものがある。

6.5.12 スケーリング

リソースのキャパシティプランニングにもとづくスケーラビリティの単純な計算方法は以下のようになる。

  1. ターゲットユーザーの規模やアプリケーションの要求のベースを見積もる。
  2. ユーザーごと、要求ごとのCPUの使用状況を明らかにする。
    • 既存のシステムでは、CPUの使用状況は、現在のユーザ数や要求頻度でモニタリングできる
    • これから開発するシステムでは、負荷生成ツールでユーザをシミュレートする
  3. CPUリソースの使用率が100%になったときのユーザー数、要求数を外挿法で計算する
    • これがシステムの理論的な限界になる

6.6 分析

CPU統計ツール・コードパスプロファイリング・CPUサイクル分析のためのツールなど、「6.5 メソドロジ」をサポートするツールや機能について。

6.6.1 uptime

ロードアベレージを表示するコマンドのなかのひとつ。

ロードアベレージ
  • CPUリソースに対する需要を示す指標
  • 実行中のスレッドと実行を待ってキューイングされているスレッドの合計数(使用率+飽和)から計算される
    • キューの長さをサンプリングせず、使用率にスレッドスケジューラのレイテンシの合計を加える、という新しい計算方法もある。従来よりも精度も高い
  • ロードアベレージ > CPU の数 の場合:スレッドを処理するCPUが足りておらず、一部のスレッドが待っている状態
  • ロードアベレージ < CPU の数 の場合:CPUに余裕がある状態
Linuxロードアベレージ
  • いまのところ Linux におけるロードアベレージには、「割り込み不能状態でディスクI/Oを実行しているタスク」を加えている
  • この値だけからではCPUとディスクの負荷がどれくらい反映されているかはわからないので、ロードアベレージはCPUだけの余裕・飽和を意味するものとしては解釈できない
  • 時間の経過とともにCPUとディスクの負荷の割合がどのように変わるかもわからないので、3種のロードアベレージの数値を比較するのも難しくなる
    • ほかのリソースの負荷も考えたいのなら、リソースタイプごとに別々のロードアベレージを計算するという手もある
  • Linux で CPU の負荷を知りたい場合は、vmstat(1)mpstat(1) が返す数字などのほかの指標を使うべき。

6.6.2 vmstat

  • 仮想メモリ統計コマンド。
  • システム全体でのCPUのロードアベレージ、実行可能スレッドの数を表示する
    • r : ランキューの現在の長さ(待機しているタスクと実行されているタスクの合計(Linux))。すべてのCPUを対象とするシステム全体での合計。
      • vmstat の man ページには「実行時間が与えられるのを待っているプロセスの数」となっているが、これは古い記述。
    • us : ユーザー時間。ブート以降の集計・すべてのCPUを対象とするシステム全体での平均。
    • sy : システム時間(カーネル)。ブート以降の集計・すべてのCPUを対象とするシステム全体での平均。
    • id : アイドル時間。ブート以降の集計・すべてのCPUを対象とするシステム全体での平均。
    • wa : I/O待ちの時間。スレッドがディスクI/Oのためにブロックされていて、CPUがアイドル状態になっている時間を計測。ブート以降の集計・すべてのCPUを対象とするシステム全体での平均。
    • st : stole された時間。仮想環境でほかのテナントにサービスを提供するために使われたCPU時間を示す。ブート以降の集計・すべてのCPUを対象とするシステム全体での平均。

6.6.3 mpstat

  • マルチプロセッサ統計ツール
  • CPUごとの統計情報を取得できる
  • %usr %sys %idle の3種が重要で、これらからCPUごとの使用状況がわかり、ユーザー時間/カーネル時間がわかる

6.6.4 sar

  • System Activity Reporter
  • 現在のアクティビティを観察することも、統計の履歴情報をアーカイブすることもできる

6.6.5 ps

  • Process Status
  • CPU使用状況の統計を含め、すべてのプロセスの詳細情報を表示する
  • Linux では %CPU 欄は、全てのCPUの合計という形で使用状況を表示する
    • ふたつのスレッドを実行するCPUバウンドプロセスは200%と表示される

6.6.6 top

  • もっともCPUを消費している実行中プロセスをモニタリングして、定期的に画面を更新する
  • 表示されるCPUの状態は mpstat(1) と同じで、CPUの使用状況は ps(1) と同じ。
  • TIME+ は分解能が 1/100 秒になっている

6.6.7 prstat

  • Solaris ベースシステム用の top として作られた。

6.6.8 pidstat

  • プロセスまたはスレッドごとにCPUの使用状況を表示し、ユーザー時間とシステム時間の分解もしてくれる。
  • デフォルトではアクティブなプロセスだけについて変化の状況を出力する
  • -p ALL オプションを使うことでアイドル状態のものも含めてすべてのプロセスを表示できる
  • -t オプションを使うことでスレッドごとの統計を表示できる

6.6.9 time、ptime

  • プログラムを実行し、そのCPU使用状況を報告させられる。
  • /usr/bin/time バージョンは、 -v オプションをサポートしており、詳細表示させることができる

6.6.10 DTrace

  • ユーザーレベルコードをカーネルレベルコードの両方について、CPUの使用状況をプロファイリングできる
    • 関数の実行、CPUクロスコール(片方のCPUがもう片方のCPUに割り込みをかける状態)、割り込み、カーネルスケジューラをトレーシングもできる

6.6.11 SystemTap

  • スケジューライベントのトレーシングに使用可能

6.6.12 perf

  • もともとは Performance Counter for Linux
  • その後プロファイリングとトレーシングのためのツールコレクションに発展、現在は Linux Performance Events と呼ばれている
  • 以下のようなことが行える
    • CPUコールパスをプロファイリングして、カーネル空間とユーザー空間のどこでCPU時間が使われたかの集計の表示
    • 個々のプロセスを対象としたプロファイリング
    • スケジューラの統計を記録・報告する
    • CPCにもとづき、CPUサイクルのふるまいについての高水準サマリをまとめる
    • カーネルスケジューラのアクティビティをトレーシングするために、perf record -e とさまざまなソフトウェアインストルメンテーションポイントの組み合わせを使うことができる(ソフトウェアトレーシング)

6.6.13 cpustat

  • Solaris ベースのシステムで CPC を解析するためのツール。

6.6.14 その他のツール

Linux を対象として、以下のようなものがある

  • oprofile : CPUプロファイリングツール
  • htop : CPU使用状況のASCIIバーチャートを含む、top(1) よりも強力な対話的インターフェースを持つツール。
  • atop : システム規模の統計を多く含むほか、プロセスアカウンティングを使って短命なプロセスの存在をキャッチする。
  • /proc/cpuinfo : クロックスピードや機能フラグなど、プロセッサの詳細がわかる
  • getdelays.c : 遅延アカウンティング可観測性ツールの例。プロセスごとのCPUスケジューラレイテンシが含まれている
  • Valgrind : メモリのデバッグ、プロファイリングのためのツールキット。

6.6.15 ビジュアライゼーション

  • 折れ線グラフ:CPUごとの使用率を表すことを考えると、今日使われているCPUの数には適していない。
  • 使用率ヒートマップ:各時間範囲ごとの使用率・飽和度だったCPUの数を、各ピクセルの色の濃さで表したもの。
  • 秒未満オフセットヒートマップ:CPUの1秒未満のアクティビティを解析できる。平均することで消えてしまうアクティビティを確認するのに有用。
  • フレームグラフ:スタックフレームのプロファイルを視覚化するための手段。

6.7 実験

CPUのパフォーマンスをテストするツールについて。これらのツールを使うときには、CPUの使用状況と並列実行を確認するために、mpstat(1) を実行し続けるとよい。

6.7.1 アドホックテスト

  • 既知のワークロードを用い、可観測性ツールが想定通りのものを表示してくれることを確認するもの。

6.7.2 SysBench

  • スレッド数を指定して素数を計算する処理などを行わせることができる。ほかのシステムやほかの構成から得られた結果との比較に使える。

6.8 チューニング

前提として、CPUのパフォーマンスを上げるためにもっとも大きな効果を得られるものは、不要な仕事を取り除くこと

6.8.1 コンパイラオプション

  • コンパイラと、コンパイラがコードの最適化のために提供しているオプションは、CPUのパフォーマンスに劇的な影響を与えることがある。
    • 64ビットプログラムとしてのコンパイルや、最適化レベルの選択、など。

6.8.2 優先度とクラスの操作

  • nice(1) コマンドを使って、プロセスの優先度を調整する。
    • 正のナイス値は優先度を下げ、負のナイス値(スーパーユーザーのみ設定可能)は優先度を上げる。

6.8.3 スケジューラオプション

  • カーネルは、スケジューラの動作を制御するためにチューニング可能なパラメータを提供している
    • このチューニングが必要になることはほとんど考えられない

6.8.4 プロセスのバインド

  • プロセスはひとつ以上のCPUにバインドすることができる。バインドさせると、キャッシュのウォーム度とメモリの局所性が上がってパフォーマンス向上に繋がる場合がある
    • Linux では taskset(1) コマンドでバインドする

6.8.5 排他的CPUセット

  • CPUをグループでまとめ、プロセスをそのグループに対応付けるもの。
  • ほかのプロセスがその cpuset を使えなくなるので、システムの他の部分で使えるCPUの数が減ってしまうというトレードオフもある

6.8.6 リソースコントロール

  • プロセスをCPU全体と対応付けるだけでなく、CPUのきめ細かい割り当てのためにリソースコントロールを提供している
    • Linux だと cgroup 。CPUの使用状況はシェアを使って制御できる

6.8.7 プロセッサオプション(BIOS チューニング)

  • プロセッサレベルでの機能を有効/無効化することでチューニングを行なうこともできる
  • 基本的にこれを調整する必要はなく、Intel Turbo Boost を無効にしてCPUベンチマークが一定のクロックスピードで実行されるようにすることを目的として設定することがもっとも大きな理由。

6.9 練習問題

全て、未・答え合わせな状態。

1. CPUの用語について

  • プロセスとプロセッサの違いはなにか。
    • プロセス:ユーザーレベルプログラムを実行するための環境のこと。メモリアドレス空間、ファイル記述子、スレッドスタック、レジスタから構成されている。ひとつ以上のスレッドを含む。
    • プロセッサ:システムやプロセッサボードのソケットに装着される物理的なチップ。
  • ハードウェアスレッドとはなにか。
  • ランキューとはなにか。
    • 実行可能状態のスレッドがCPUリソースの割り当てを待っている、その待ち行列のこと。
  • ユーザー時間とカーネル時間の違いは何か。
    • ユーザー時間:ユーザーレベルコードの実行に使用されたCPU時間のこと。
    • カーネル時間:ディスクI/Oなどのシステムコールにより使用されたCPU時間のこと。
  • CPIとはなにか。
    • Cicles Per Instruction。命令のコストの大きさを示す指標。命令処理の効率性を示す指標。これが高いということは、CPU がストールしていることが多いということになる。

2. コンセプトについて

  • CPUの使用率と飽和の説明
    • 使用率:一定期間内で CPU インスタンスが仕事をしていてビジー状態になっている時間の割合を%で表現したもの。CPUの使用率が高いのはかならずしも問題ではない。使用率が高くなっても、カーネルが優先度・プリエンプション・タイムシェアリングをサポートしているため、パフォーマンスはかならずしも大きく下がるとは限らない。
    • 飽和:使用率100%のCPUは飽和しており、スケジューラレイテンシの影響を受けて、全体としてのパフォーマンスは下がる。CPUの飽和には、クラウドのマルチテナント環境などで設定されるCPUリソースコントロールによるものもある(CPUの使用率が100%にならなくても、設定された限界に達すると、同じく飽和と似たような状態となる)。
  • 命令パイプラインがCPUのスループットをどのようにして上げるのかを説明
    • 同じ回路で複数の命令をオーバーラップさせて実行することで、複数の命令を並列実行させることができ、スループットを向上させる。
  • プロセッサ命令幅がCPUのスループットをどのようにして上げるのかを説明
    • 上記命令パイプラインにおいて、並列処理できる命令の数のことを命令幅と呼ぶ。この数が増えることで、一度にオーバーラップさせて実行できる命令の数も増えるため、全体としてのスループットも向上する・
  • マルチプロセス、マルチスレッディングモデルの利点を説明
    • マルチプロセス:プロセスごとにアドレス空間が別々になる分、メモリオーバーヘッドは大きいが実装は比較的平易
    • マルチスレッディング:マルチプロセスモデルに比べてメモリやCPUのオーバーヘッドも小さい。各スレッドは共有メモリに直接アクセスできるため、スレッド間でのやりとりも高速。

3. 少しむずかしい問題

  • システムCPUが実行可能要求によって過負荷になっているときに何が起きるか、アプリケーションのパフォーマンスに対する影響を含めて説明
    • 実行可能プロセス(スレッド)はスケジューラによりCPUリソースを与えられるのを待つ。スケジューラは、各プロセス(スレッド)の優先度やnice値などを考慮して適切な順番でCPUリソースを与えていく。そのため、全体としてのパフォーマンスは大きく下がることはなくても、全体としては下がる。
  • 実行すべき実行可能要求がないとき、CPUは何をするか。
    • アイドルスレッドを実行している。
  • CPUのパフォーマンスの問題かもしれないものの処理を委ねられたときに、調査の初期の段階で使う3つのメソドロジを挙げ、その理由を説明
    1. USEメソッド:本当にCPUのパフォーマンス問題なのかどうかを切り分ける。使用率が100%なのかどうか。飽和の度合いはどれくらいなのか。
    2. ツールメソッド:CPU使用率の内訳を確認する。ユーザー時間/カーネル時間?ディスクI/O?swap発生の有無?ストールの有無?
    3. プロファイリング

4. 手順を考える

  • CPUリソースのためのUSEメソッドチェックリスト。個々の指標の取得方法と結果の解釈方法も入れること。
    • uptimeロードアベレージを確認することで飽和の度合いを確認できる
    • mpstat top で(CPUごとの)ユーザー時間/カーネル時間の使用状況を確認できる
  • CPUリソースのワークロードの特性の把握チェックリスト。個々の指標の取得方法と結果の解釈方法も入れること。
    • vmstat : システム全体でCPUの使用率はどうなっているか。また、CPUごとではどうか。
    • mpstat : CPUの負荷はどれくらい並列化されているか。シングルスレッドか。スレッドはいくつか。
    • top ps : どのアプリケーション、またはユーザーがCPUをつかっているか。それはどのくらいか。
    • top ps : どのカーネルスレッドがCPUを使っているか。それはどのくらいか。
    • /proc/stat : 割り込みのCPU使用状況はどれくらいか。
    • CPCベースのイベントトリガを使ってのプロファイリング : CPUインターコネクトの使用率はどれくらいか。
    • DTrace : CPUはなぜ使われているか。ユーザー/カーネルレベルのコールパスはどうか。
    • サイクル分析 : どのようなタイプのストールサイクルが発生しているか。

5. 設問



follow us in feedly