That's Done!

thatsdone's (mostly technical) memorandum

[ja] Methodologies of Systems Performance - Brendan Gregg


Brendan Gregg の "Systems Performance: Enterprise and the Cloud" という本があります。 (翻訳はこちら) 言わずと知れた DTrace の作者が書いた本で、 全体的な考え方から、CPU・メモリ…等と、具体的な観点ごとに包括的かつ詳細に解説されているので非常によい本です。 軽い勉強会みたいなやつで使おうと思って、まずは方法論(Methodology)が書いてある2章のまとめを作っています。 …が、書いてみたら、結局、目次を追っていくのが一番いいのかなー…という結論に(笑)

なお、昨年末に"BPF Performance Tools"という新しい本も出ていて買ったのですが、 私は発送待ち状態です。いつ日本に来るんでしょうか?(苦笑) まあ、eBPF/XDPについてはこれ も読んだので、まあぼちぼちでいいっちゃいいのですが。(笑)

一番大事なところ - 方法論の章(2章)の構成

方法論(Methodology)は2章になります。 この章だけでけっこうな分量になるので、まずは全体を俯瞰するという意味で、目次構成を眺めるだけでも意味があるでしょう。 目次の構成をそのまま引用しながらまとめていきます。少し長いですが、落ち着いて眺めてみると頭が整理できると思います。

なお、著者本人は、冒頭でこの章をざっくりまとめると以下の3点であると書いています。 2.5節の具体的な方法論と、これらを使うときに使う具体的な Metric の2点が大事なのであって、 他はみんなこの2点を使うための背景知識なのだというわけです。

  1. Background
  2. Methodology
  3. Metrics

以下、2章の目次にしたがって見ていきます。(ただし、まだ書きかけ)

2. Methodology ★一番大事な章★

2.1 Terminology # まずは用語定義

2.2 Models # モデル

2.2.1 Systems Under Test

評価・分析するシステム自体のモデル化しておく。いわゆるSUT。

2.2.2 Queueing System

待ち行列理論 = 数理モデルの基本

ちなみにこんな本もありますね。Performance Modeling and Design of Computer Systems: Queueing Theory in Action

2.3 Concepts # 基本概念

この節、個人的には項目の選択とか並びが ad hoc すぎるのではないか?という感がありますが、それは別途整理するとして、並んでいる順番に見ていきます。

2.3.1 Latency

一言で「通信遅延」と言っても、測定する場所によって、例えばコネクション接続+データ転送+処理時間…等分解されるのに注意。

2.3.2 Time-Scales

CPUの命令サイクル、メモリアクセス、DISKアクセス…等、モノによってかかる時間のスケールが違うのに注意。

2.3.3 Trade-offs

例えば、I/OサイズとI/O性能・I/Oパターンの関係等、両立しないものの間のトレードオフを知ること。

2.3.4 Tuning Efforts

アプリ~MW~OS~ハードのどのレイヤで性能チューニングを施すのか?一般論としては(アプリに近い)上のレイヤで実施するほど効果は高い。

2.3.5 Level of Appropriateness

性能分析、チューニングにどこまでコストをかけて深堀りするのかは組織としての投資対効果による。

2.3.6 Point-in-Time Recommendations

チューニングパラメータの推奨値は、条件によって変わるものなので「その時点のもの」(point-in-time)と思うべし。

2.3.7 Load versus Architecture

システムの性能に影響するのは個々のソフトの「設定値」だけでなく、システムの構造(アーキテクチャ)に由来することもある。

2.3.8 Scalability

スケーラビリティ=負荷量に対する性能値のふるまい。ふるまいの変化は、スループットの場合はリニアな伸びが変わるところ、レスポンスは一定値(≒リニア)から徐々に劣化が始まるところで見える。典型的な理由は、(なんらかの)リソースの utilization が 100%に達すること(saturation)。

2.3.9 Known-Unknowns

いわゆるknown-known/known-unknown/unknown-unknown。性能評価を進めるにしたがって、unknown-unknownに気づいていくのに注意。

2.3.10 Metrics

実際に見る具体的な指標。例としては、IOPS、troughput、utilization、latenc等々。忘れてはいけない大事な点として、1) metricの採取自体にもコストがかかること、2) metricの定義や実装そのものに信頼がないようなケースもあること。

2.3.11 Utilization

利用率には「時間(time)ベース」と「容量(capacity)ベース」の2つがある。前者は単位時間あたりに仕事をしていた時間(busy率)で、後者は処理可能な容量に対する割合。特に前者のbusy率の場合、リソースによっては多重処理が可能なケースもあるので、utilization が100%であっても限界とは限らないのに注意が必要。

cloud (というか、仮想化)環境の場合には、non-idle time という見方をしたほうがよいという考え方もある。

2.3.12 Saturation

saturation (飽和)状態とは、処理可能な量を超えて、どの程度のリクエスト(仕事)量が流入しているかを示す程度。処理しきれないリクエストは、待ち行列につながることになる。

2.3.13 Profiling

一般論としては、調べて理解できるような対象システムの「描像」を得ること。実際のシステムの Profiling では、典型的にはサンプリングが基本であって、(サンプル間隔しだいだが)得られる描像は荒い(疎な)ものになるの注意。

2.3.14 Caching

本書では後ろの方でキャッシングとバッファリングの違いの話も出てきますが、ここではキャッシュのヒット率と性能の関係、キャッシュのアルゴリズム(MRU/LRU/MFU/LFU)や、キャッシュされたデータのCold/Hot/Warmという分類(と、キャッシュ暖かさ(Warmth)という用語)が出てきます。

2.4 Perspectives # 全体像

性能分析には、大きく、1. Resource Analysis と 2. Workload Analysis の2つの側面がある。

1.の Resource Analysisには文字通りリソースの利用状況の分析であり、さらに a) 性能問題の調査と、b) Capacity Planning が含まれる。

2.の Workload Analysisはアプリケーションの構造を鑑みて指標(SLIかな)をどう定義するのか?という話で、典型的には Latency(Response)とThroughputが含まれる。

2.5 Methodology # 方法論(★一番大事なところ★)

この節は一番大事なところなのですが、2.3 Concepts と同様に、並んでいる順番が少し ad hoc すぎないか?という気がしています。

2.5.1 Streetlight Anti-Method

Anti-Method(やっちゃダメ)な例。意図的な方法論がないケースのこと。適当に探してなんとなく見つかったツールで測定した指標を使うということで、検出された問題は実際のところは問題なこともあるし問題でないこともある。

2.5.2 Random Change Anti-Method

これも Anti-Method。原因になっていそうポイントをランダムに想定し、その条件を問題が消えるまで変え続けるということ。

2.5.3. Blame-Someone-Else Anti-Method

同じく Anti-Method。自分の担当範囲外の部分を見つけて、そこに原因があるという仮説を立てて担当チームに押し付ける。(ごくまれによく採用される方法論...gkbr)

2.5.4 Ad Hoc Checklist Method

定型のチェックリストにしたがう方法。チェックリスト自体は最短時間で多くの範囲をカバーできるが、あくまでその時点での推奨であって、頻繁に更新する必要があるのに注意。

2.5.5 Problem Statement ★最重要★

新しい問題に取り組むときには最初にとるべき方法。以下のような手順で、問題を具体的に書き下して定義していきます。これによって、問題点がわかることも多いです。

  1. 性能問題があると考えた理由は何か?
  2. 今まで想定どおりに動いていたか?
  3. 最近何か変えたか?
  4. 問題はlatencyかthroughputの指標で表せるか?
  5. その問題は、他の人やアプリケーションに影響を及ぼしているのか?それとも自分だけか?
  6. 環境は?どんなソフトとハードを使っているのか?バージョンは?設定は?

2.5.6 Scientific Method ★重要★

通常の自然科学の研究でとるアプローチ。

  1. 課題設定(Question)
  2. 仮説を立てる(Hypothetis)
  3. 予想をたてる(Prediction)
  4. テスト(Test)
  5. 分析(Analysis)

最初の 'Question' は 2.5.5の Problem Statement であって、これが出発点になる。

2.5.7 Diagnosis Cycle ★重要★

Scientific Method と似ているが。仮説をたてる → 計測する → 分析する → 新しい仮説をたてる…という分析的なアプローチ。

2.5.8 Tools Method

手順は「使えるツールのリストを作る → 各ツールで得られる有用なmetricの一覧を作る → 各metricの解釈のルールを作る」。これが完璧というわけではないし、十分とは言えないこともあるが、現実的にはこの方法でリソースのボトルネックやエラー等の問題を検出できる。

2.5.9 The USE Method ★重要★

まず特定のリソースに着目、当該リソース関連のErrorがあるか?、Utilization は高いか?Saturationが発生しているか?の十番で事象の発生有無をチェックし、検出した事象が原因なのかどうか検討する。原因でなければ次のリソースに着目するという手順をとる。

着目すべきリソースは、リソースの一覧表を使う(CPU/Memory/Network/Storage/Controller等)、機能ブロック図(例として図2.13)から考える方法がある。

リソースの種別ごとに様々な metric がある。(表2.5と表2.6)手元のツールで取得できない metric は known-unknownとして意識しておくべき。

CPUのようなハードウェアリソース以外に「ソフトウェアリソース」がある。例えば、mutex lock の衝突数等、thread poolの空き状況等。

解釈の例

  • Utilization
    • きちんと評価するには、待ち行列を使って考えるべし。
  • Saturation
    • 飽和状態が発生しているということは問題な可能性がある。待ちキューの長さ滞留時間を調べる。
  • Error
    • エラーのカウンタが0でなく、数値が増え続けているのであれば調べる価値がある。

2.5.10 Workload Characterization

「ワークロードの説明」をしておくのは、問題点を明らかにするための良い方法。以下の4つを問うことによって説明できる。

  1. Who : 誰が負荷を発生させているのか? PID?UID?remote IP address?
  2. Why : なぜその負荷が発生しているのか?code pathをstack traceで調べる?
  3. What : その負荷の特徴は?IOPS?throughput?方向(read/write) ?分散(や標準偏差)も込みで。
  4. How : その負荷には時間に依存したパターンがあるか?日時など。

2.5.11 Drill-Down Analysis

いわゆる段階的詳細化。以下の3段階がある。

  1. Monitoring
    • 継続的にリソースの監視を行う。
  2. Identification
    • 特定のリソースの挙動によって、ありうるボトルネックを特定する。
  3. Analysis
    • 根本原因の特定と問題の定量化を試みる。

「なぜは5回くりかえせ」…って、某自動車メーカーでも言っていますね。 ただし「5回」自体にはあまり意味はなくて、例えば "human error" で「なぜ」の追及をやめるな…等、あります。

2.5.12 Latency Analysis

1つのリクエストの処理を細かい部分処理に分解・分析していく。根本原因を特定・定量化できるように、最も時間のかかっている部分処理を調べる。

2.5.13 Method R (by Oracle)

Oracleのツール固有の話。SQL Query の 2.5.12 Latency Analysisに相当する。

2.5.14 Event Tracing

システムの動きは離散的なイベントの処理ということができる。ここでいうイベントとは、CPU命令とか、DISKコマンドとか、Networkパケットのような低レイヤのものから、SQLクエリなどもイベントとみなせる。

性能分析とは、これらのイベントのサマリを検討することであり、例えば、単位時間あたりの操作、単位時間当たりのデータ量などが含まれるが、 サマリ(集計値)に詳細が埋もれてしまうこともある。

例として、systemcallのトレース(strace)、I/Oトレース(Solarisのiosnoop)、パケットダンプ(tcpdump)が挙げられている。 …が、perf (というか BPF/eBPFや、昔は systemtap)を使うことによって、多彩な種類のイベントをイベント単位で知らべることもできる。

2.5.15 Baseline Statistics

基準になる性能値とその時の各種リソースの値等を採取しておくこと。

これはまあPOCするときの基本ですね。

2.5.16 Static Peformance Tuning

静的性能チューニングは、例えば、NICのportが意図のリンク速度でLINK UPしているか?等の設定、状態を確認していくこと。

2.5.17 Cache Tuning

  • そもそもキャッシュ機能が有効になっているか?
  • キャッシュのヒット率/ミス率
  • キャッシュサイズが動的に変わる場合の現在のサイズ
  • 複数レイヤにキャッシュがある場合、処理をしている一番近くでキャッシュが効いているか?
  • CPUキャッシュ(L1/L2/L3)の場合、レイヤごとに削れるレイテンシと効果が異なってくる。

2.5.18 Micro-Benchmarking

アプリケーションレベルだと負荷自体が複雑になりすぎて問題点がわかりにくいことも多いが、「ピンポン通信」等の、これ以上分解できないくらい細かい視点でのベンチマーク。

2.6 Modeling

2.6.1 Enterprise versus Cloud

TBD

2.6.2 Visual Identification

性能特性をグラフにしてみると、特徴的なパターンがいくつかある。

  • Linear scalability (線形)
  • Contention (競合)
  • Coherence (干渉)
  • Knee point (適切な日本語が見つからないのだが、まあ折れているということ)
  • Scalability Ceiling (天井にあたったように水平になってしまうこと)

2.6.3 Amdahl's Law of Scalability

いわゆるアムダールの法則。

C(N) = N/(1 + α(N-1))

2.6.4 Universal Scalability Law

C(N) = N/(α(N-1) + βN(N-1))

2.6.5 Queueing Theory - 待ち行列理論

待ち行列大事。典型的には以下くらい?

  • M/M/1
  • M/M/c
  • M/G/1
  • M/D/1

2.7 Capacity Planning

TBD

2.7.1. Resource Limits

2.7.2 Factor Analysis

2.7.3 Scaling Solutions

2.8 Statistics

統計も大事。だが、TBD。

2.8.1 Quantifying Performance

2.8.2 Averages

「平均値」って何種類もあるって意識していただろうか?

  • アルキメデスの3平均
    • Arithmetric - 算術平均(一番普通に使うやつ)
    • Geometric - 幾何平均
    • Harmonic 調和平均(Fの定義で出てきますね)
  • Averages over Time
  • Decayed Average

2.8.3 Standard Deviationos, Percentiles, Median

2.8.4 Coefficient of Variation

2.8.5 Multimodal Distributions

2.8.6 Outliers

  • Anomaly???

2.9 Monitoring

2.9.1 Time-Based Patterns

2.9.2 Monitoring Products

  • Summary-since Boot

2.10 Visualizations

2.10.1 Line Chart

2.10.2 Scatter Plots

散布図の有用性をちゃんと意識している人って少ないような気がする。

2.10.3 Heat Maps

2.10.4 Surface Plot

2.10.5 Visualization Tools

2.11 Exercises

2.12 References

13. Case Study : むかーし、Redis がナニモノかも知らなかった頃の話