tech3分で読める

性能テスト・負荷テスト

性能テストを「速い/遅い」を測る作業ではなく、SLO達成とボトルネック特定のための実験として設計する。普遍的な考え方と、現代ツールのざっくり比較表をまとめます。

#負荷テスト#ロードテスト#パフォーマンス#SRE#SLO#observability#k6#locust

性能テストと負荷テスト(Load)の関係

仮説を置いて、再現可能な条件で、システムの限界と弱点を見つける実験です。

ここでの位置づけは次の通りです。

  • 性能テスト(Performance Testing): 上位概念(性能を様々な条件で検証する)
  • 負荷テスト(Load Testing): 性能テストの一種(想定〜ピーク負荷での挙動を検証する)

用語整理(このドキュメントの呼び方)

結論から言うと、標準的な定義では 「性能テスト(Performance Testing)」が上位概念で、その一種が「負荷テスト(Load Testing)」 です。 一方で日本語の現場では「負荷テスト」という言葉が 性能テスト全般(ロード/ストレス/スパイク/ソーク等)をまとめて指すこともあり、会話だけだとズレやすいです。

このドキュメントでは混乱を避けるため、以下のルールで呼び分けます。

  • 性能テスト」: 上位概念としての話(目的、指標、進め方など“全般”)
  • 負荷テスト」: Load Testing を指す(想定〜ピーク負荷)
  • Load以外は「ストレステスト」「スパイクテスト」「ソーク(耐久)テスト」「キャパシティテスト」と書く
呼び方位置づけざっくり何をする?何が分かる?
性能テスト(Performance Testing)上位概念性能(応答/スループット/安定性/資源効率/スケール)を様々な条件で測るSLO達成可否、劣化傾向、改善余地
負荷テスト(Load Testing)性能テストの一種想定〜ピークの負荷(同時ユーザー/RPS等)で振る舞いを見る想定負荷で壊れないか、どの辺から苦しくなるか
ストレステスト(Stress Testing)性能テストの一種想定を超えて負荷を上げ、限界点と壊れ方を見る限界点、フェイルの仕方、回復性
ソーク/耐久テスト(Soak/Endurance)性能テストの一種中〜高負荷を長時間かけ続けるメモリリーク、枯渇、劣化の蓄積
スパイクテスト(Spike)性能テストの一種短時間で急増/急減させるバースト耐性、回復の速さ

※ 定義は団体/ベンダーで表現が少し違いますが、「性能テストが上で、負荷テストはその一部」という関係は概ね共通です。 参考:


性能テストはなぜ行うのか(そもそもの目的)

結論として、性能テストの目的は 「想定される(または最悪の)負荷条件で、サービスが約束(SLO/UX/安全性)を守れるかを、再現可能に検証して“失敗の仕方”まで把握すること」 です。

さらに一段抽象化すると、負荷というストレスをかけたときに、システムがどう振る舞うかを実験で理解し、予測可能にすることです。 そして、それをする理由は結局 本番で起きる高コストな失敗(障害・炎上・機会損失)を、事前に安く・安全に・再現可能に潰すためです。

  • ユーザー体験の保証: 想定トラフィックで p95/p99 が許容範囲か、タイムアウト/エラーが増えないか
  • 限界点とボトルネック特定: どこ(DB/外部API/キュー/コネクション/CPU/IO)が先に詰まるか
  • キャパシティ計画: 「今の構成で何RPS(Requests Per Second)まで」「何を増やすと伸びるか」を数字で持つ
  • スケール/保護機構の検証: オートスケール、レート制限、リトライ等が期待通り動くか
  • 回帰検知: リリースや設定変更で性能(特にテイル)が悪化していないか

それぞれはどの“種類”のテストに関係する?

上の箇条書きは「目的/観点」で、そこから「どの種類の性能テストをやるか」を選びます(1対1ではなく、複数が当てはまることがあります)。

目的/観点関連するテスト種別(例)
ユーザー体験の保証負荷テスト(Load)、ソーク(耐久)
限界点とボトルネック特定ストレステスト(Stress)
キャパシティ計画キャパシティテスト(Capacity)(実施形態として負荷/ストレスを使うことも多い)
スケール/保護機構の検証負荷テスト(Load)、スパイクテスト(Spike)、(場合により)ストレステスト
回帰検知既定シナリオの性能テストをベンチマーク化して継続実行(多くは負荷テストで実施)

性能テストで得られるメリット / デメリット(負荷テストを含む)

メリット

  • 本番前に弱点が見える: 限界点・詰まり(サチュレーション)・依存先の律速を早めに発見できる
  • 数字で意思決定できる: 「どこまで出せるか」「何を変えるとどれだけ効くか」を比較できる(勘や体感に頼らない)
  • 回帰を早期に検知できる: リリースや設定変更で p95/p99 やエラー率が悪化していないかを継続的にチェックできる
  • 運用の不安が減る: アラート設計、オートスケール、レート制限などの運用機構も含めて検証できる

デメリット(コスト・注意点)

  • 時間とコストがかかる: シナリオ作成、テスト環境整備、データ準備、観測、解析に工数が必要
  • 現実を完全には再現できない: キャッシュ、データ分布、ユーザー行動、外部要因(ネットワーク/依存先)で結果がズレる
  • 観測が弱いと「分かった気」になる: 原因が特定できないまま終わりやすい(メトリクス/トレース/ログが必須)
  • 環境に影響を与える: テスト環境でもDBを痛めたり、依存先に迷惑をかける可能性がある(制限や隔離が必要)

まず決めるべきこと(試験の目的)

  • SLOを満たせるか確認したい 例: 「p95 300ms以下」「エラー率 0.1%以下」「月間可用性 99.9%」など
  • ボトルネックを特定したい 例: DB、外部API、キャッシュ、コネクションプール、ロック、CPU、I/O
  • スケール戦略を検証したい 例: オートスケールが効くか、キューで吸収できるか、上限はどこか
  • リリース前の回帰検知をしたい 例: 以前よりp99が悪化していないか、リソース効率が落ちていないか

目的が曖昧だと、結果が「なんとなく速い/遅い」で終わりがちです。

目的によって試験の進め方は変わる?

変わります。目的ごとに「負荷の作り方」「観測すべき指標」「合否判定(または成果物)」が変わります。

目的進め方(負荷のかけ方)何を見る(合否/成果)
SLOを満たせるか確認想定トラフィックで定常状態を一定時間維持(Load/Soak寄り)p95/p99、エラー率、タイムアウト率がSLO内か
ボトルネック特定低負荷→段階的に上げる Ramp/Stress で崩れ方を見る律速箇所(DB/依存先/コネクション等)と次の打ち手の仮説
スケール戦略検証スケールアウトが発火するよう負荷をかけ、スケールに要する時間も測る(Spikeも有効)スケール中のSLO逸脱、回復可否、保護機構(レート制限等)の動作
回帰検知条件固定で毎回同じシナリオを再現し、前回/基準と比較p95/p99、エラー率、リソース効率の悪化が許容範囲内か

見るべき指標(性能テスト全般で共通)

レイテンシ(特にテイル)

  • p50 / p95 / p99: 平均より「遅い人」を見る(ユーザー体感はテイルが支配しやすい)
  • 分解: DNS/接続/待ち/処理/DB/外部API など、どこに時間があるか

スループット

  • RPS/TPS: どれだけ処理できたか(ただし、速い=良いではなく「SLOを満たしながら」が条件)

エラー

  • HTTP 5xx/4xx、タイムアウト、リトライ回数 タイムアウト増は「遅い」ではなく「壊れ始めている」兆候です。

サチュレーション(詰まり)

  • CPU/メモリだけでなく、DB接続枯渇スレッド枯渇キュー滞留I/O待ち外部APIのレート制限など

観測はよく「RED(Rate/Errors/Duration)」や「Golden Signals(Latency/Traffic/Errors/Saturation)」で整理できます。


性能テストの種類(使い分け)

種類目的代表的なやり方
Load想定負荷でSLO達成想定トラフィックで定常状態を維持
Stress限界点・崩れ方の把握徐々に上げてどこで壊れるかを見る
Spike急増への耐性瞬間的に跳ね上げる(SNS拡散など)
Soak長時間の劣化検出メモリリーク、枯渇、GC悪化を炙る
Capacity受け入れ上限の見積り「いまの構成で何まで」→増設計画へ

シナリオ設計(現実に寄せる)

ユーザー行動にする(単一APIだけにしない)

例:

  • ログイン → 一覧 → 詳細 → 更新
  • 検索 → 絞り込み → 購入 → 決済(外部連携)

データを現実に寄せる

データが少ないとインデックスやキャッシュが効きすぎて、本番より良い結果になります。 逆に、毎回同じIDを叩くとキャッシュが効きすぎます(ホットキー問題も起きます)。


ワークロードモデル(ここが精度を左右)

負荷の作り方は大きく2系統です。

  • Open model(到着率): 例「毎秒200リクエスト来る」 インターネットの流入に近い。飽和すると待ち行列が伸び、レイテンシが崩れるのが見えやすい。

  • Closed model(同時ユーザー): 例「同時200ユーザー」 レイテンシが伸びると、その分リクエスト発行が遅くなり到着率が落ちる(現実とズレることがある)。

どちらでも良いのではなく、目的に合うモデルを選ぶのが重要です。 (例: “SNS流入の急増”を見たいなら到着率モデルが合いやすい)


試験の進め方(テンプレ)

  • 前提: 環境・構成・データ量・キャッシュ状態を固定(差分が結果を歪める)
  • Warm-up: JIT/キャッシュ/コネクション確立のための準備運転
  • Ramp: 徐々に上げる(いきなり最大にしない)
  • Steady: 定常を維持して観測(ここが本番)
  • Cool-down: 終了後の回復具合も見る(スレッド/コネクションが戻るか)
  • 再現性: 同条件で複数回(「たまたま速い/遅い」を排除)

よくある落とし穴(時代が変わっても同じ)

  • キャッシュで“良く見える”(本番の分布と違う)
  • 外部APIが律速(レート制限・遅延・障害注入)
  • メトリクスが足りず原因不明(観測不足が最大の敵)
  • 負荷装置が先に限界(クライアントCPU/ネットワーク/コネクション数)
  • オートスケールの遅さ(スケールアウトの時間=実害)
  • コネクションプール枯渇(DB/HTTPクライアント/スレッド)
  • “平均”だけ見て安心する(p99が地獄、が典型)

結果のまとめ方(読む人に優しい)

最低限これだけあると意思決定に使えます。

  • 条件: 構成、バージョン、データ量、キャッシュ状態、実行時間、負荷モデル
  • 結果: p50/p95/p99、RPS、エラー率、サチュレーションのピーク
  • 結論: SLOを満たした/満たさない、限界点、次の打ち手
  • 打ち手: 何を変えるとどれだけ改善する見込みか(仮説→再試験)

現代のツール(ちらっと比較表)

「何を測るか(HTTP/API/ブラウザ/キュー)」で選ぶのが基本です。

目的ツール例特徴
HTTP/API の負荷生成k6 / Locust / JMeter / Gatling / Artilleryシナリオ駆動。到着率/同時数などモデル選択がしやすい
高速・単機能ベンチwrk / wrk2 / vegeta単純なHTTPを高RPSで叩く(再現性は高いがシナリオは弱め)
ブラウザE2E負荷(UI体感)Playwright / Puppeteerフロント描画やJS実行を含む(重いので台数が必要)
観測(メトリクス/トレース/ログ)Prometheus+Grafana / OpenTelemetry / Datadog / New Relic性能テストは「観測できるか」が勝敗を分ける
障害注入(レジリエンス)AWS FIS など遅延/停止/ネットワーク断で「壊れ方」を検証

すぐ使えるチェックリスト

  • 目的: SLO検証?ボトルネック探索?回帰?
  • モデル: 到着率(open) or 同時ユーザー(closed)
  • 観測: p95/p99、エラー率、サチュレーション、依存先のメトリクス
  • 再現性: 条件固定、複数回、差分があれば理由を記録
  • 安全: 本番実施はレート制限・影響範囲・ロールバック計画を用意

RK

1997年生まれ

ITエンジニア

インフラ・SRE