7分

isutools — 1行で組み込めるISUCON用オールインワンプロファイラ

isucongoossperformanceprofiling

ISUCON の計測は、道具が分散しがちだ。SQL は pt-query-digest、アクセスログは alp、CPU は top と pprof、設定は目視 — ベンチのたびに4つの端末を行き来して、結果はどこにも残らない。

isutools は、これを 1つのダッシュボードに集約する Go 製 OSS(MIT) だ。組み込みは実質1行。ベンチごとにスナップショットが自動で残り、実行間の diff まで取れる。

isutools ダッシュボードの実行履歴一覧。ベンチごとのスコアとgitリビジョンが時系列で並ぶ
isutools ダッシュボードの実行履歴一覧。ベンチごとのスコアとgitリビジョンが時系列で並ぶ

私はこれを使って private-isu を1日でスコア 0 → 541,650 にした。その実戦記録は別記事に全部書いたので、この記事は isutools 自体の導入と機能にしぼる。

クイックスタート

go get github.com/ekusiadadus/isutools

アプリ側の変更はこれだけ:

// before
db, err := sqlx.Open("mysql", dsn)
 
// after — SQL計測 + 管理サーバが有効になる
db, err := sqlx.Open(isutools.SQLDriverName("mysql"), dsn)

これで http://localhost:19191/ に管理ダッシュボードが立つ。HTTP のパス別計測も足すなら:

http.ListenAndServe(":8080", isutools.HTTP(r))

計測の運用はベンチスクリプトに2つの POST を足すだけ:

curl -XPOST localhost:19191/reset   # 計測をゼロクリア
./run-benchmark
curl -XPOST "localhost:19191/save?score=123456"  # スコア付きで保存

保存された実行はホームに日時 ID で一覧され、クリックすればその時点の全計測が開く。スコアと git リビジョンが常に一緒に記録されるので、「どのコミットで何点だったか」が消えない。

何が見えるか

1回のベンチで、以下がすべて1ページに揃う。

  • SQL — 正規化クエリ別の合計時間・回数・p95。WHERE id = 999WHERE id = 1 も同じクエリとして集計される
  • HTTP — パス別のレイテンシ集計。ISUTOOLS_PATH_RULES の正規表現で /@user1 /@user2/@* に正規化できる
  • nginx アクセスログ — alp 相当の集計を LTSV / JSON 両対応で。ボリューム共有するだけ
  • プロセス + マシン全体の CPU — どのプロセスが CPU を占有しているかに加え、busy/idle の内訳で「そもそもハードを使い切れているか」が分かる
  • DB スキーマ — ベンチ開始時点のテーブル・インデックス一覧。「インデックス貼ったっけ?」を目視でなくログで確認できる
  • pprof — reset に連動して CPU プロファイルを自動採取
  • カウンタ APIisutools.Count("user_cache_hit") で任意の値を計測。キャッシュヒット率の確認に
  • User Flow — セッション単位のページ遷移上位。ベンチマーカーの行動パターンが見える

advisor — 「未設定の定石」を自動検出

個人的にいちばん気に入っているのが advisor だ。MySQL・nginx・OS・Go の設定を読んで、ISUCON の定石なのに未設定のものを指摘する。

isutools の Advisor セクション。MySQL・nginx・OS・Go の未設定の定石を自動検出して表示
isutools の Advisor セクション。MySQL・nginx・OS・Go の未設定の定石を自動検出して表示

private-isu の初回実行では「interpolateParams なし(プリペアドで2往復)」「nginx gzip なし」「innodb_buffer_pool_size がデータ量の9分の1」を即指摘してきた。3件適用でスコア +16%。直すと ok に変わるので、チェックリストとしてそのまま機能する。

diff — 「改善したのか、移動しただけか」

チューニングで本当に怖いのは、改善したつもりでボトルネックが移動しただけのケースと、良かれと思った変更が別の場所を壊すケースだ。isutools は実行間の diff をクエリ別・パス別に出す。

isutools の diff ビュー。2つのベンチ実行間でクエリ毎の合計時間の増減を緑(改善)と赤(悪化)で表示
isutools の diff ビュー。2つのベンチ実行間でクエリ毎の合計時間の増減を緑(改善)と赤(悪化)で表示

私はこれで「インデックスを1本追加したらタイムラインの JOIN が260倍遅くなった」事故を数分で特定できた(オプティマイザが新インデックスに誘導されて実行計画が壊れていた)。

オーバーヘッドは誤差内

計測ツールがスコアを下げては本末転倒なので、ABBA 計測(off→on→on→off の4回ベンチ)で検証してある。結果は -0.58%、誤差内。手順は examples/abba.sh として同梱してあるので、自分の環境でも再現できる。

リモート計測 → 手元で閲覧

競技サーバーで計測して、スナップショットファイルをダウンロードし、手元の PC でダッシュボードを開く運用を最初から想定している。データは ISUTOOLS_DATA_DIR 配下のファイルだけで完結し、外部への通信は一切ない。

管理サーバはデフォルトで 127.0.0.1 のみ。リモートに公開する場合はトークン認証が必須で、未設定なら fail-closed(拒否)になる。SSH トンネル前提の運用だけ、明示的な環境変数で無認証を選べる。

FAQ

Q. sqlx 以外でも使える?database/sql のドライバプロキシとして動くので、sql.Open 直でも各種 ORM でも、ドライバ名を渡せるものなら使える。

Q. 本番の Web サービスでも使える? — 設計は ISUCON 特化だが、Go 製 Web アプリの性能調査には普通に使える。常時運用の APM が欲しいなら OpenTelemetry 系が本筋。

Q. 複数台構成は? — 現状は1台の計測が対象。DB 分離などの複数サーバー構成対応はロードマップにある。

リンク