rack-mini-profiler の flamegraph から機械可読な stackprof データを抜いて集計する
ただしこの出力は人間用の speedscope HTML なので、AI/エージェントには読めない。
そこで、その HTML 内に埋め込まれた var graph = {...} を抜く。これは生の stackprof JSON (raw 形式: mode / interval / samples / frames …) なので、機械可読に集計できる。
何も追加で仕込まずに済み、再現可能で、対策の before/after を同じ方法で定量比較できるのが利点。
手順1: flamegraph HTML を取得して graph JSON を抜く
wall モードで取得する (cpu / object / custom も可)。認証が要るページなら Cookie 等を適宜付ける。
code:bash
-o /tmp/flame.html
# var graph = {...}; の 1 行を取り出して JSON 化
grep -m1 'var graph = ' /tmp/flame.html | sed -E 's/^:space:*var graph = //; s/;:space:*$//' > /tmp/graph.json
手順2: 集計する
frames の samples が self、total_samples が total。ホットスポットは self% で見る。
code:python
import json; g=json.load(open('/tmp/graph.json')); S=g'samples' rows=[(v.get('name'),v.get('samples',0),v.get('total_samples',0)) for v in g'frames'.values()] for n,s,t in sorted(rows,key=lambda r:-r1):25: print(f"{s:5d} {100*s/S:4.1f}% tot={t:5d} {n}")
注意
middleware フレームは total ≒ 100% になる (リクエスト全体をラップしているだけ) ので、ボトルネック特定は total ではなく self を見ること。
self 時間を用途ごと (例: DB/ORM の属性アクセス、文字列生成、GC の (sweeping)/(marking)、IO 待ちの Kernel.select など) に束ねると傾向が掴みやすい。束ね方はアプリ依存。
flamegraph_mode は wall / cpu / object / custom。flamegraph_sample_rate はサンプリング間隔 (ms)。
全オプションは ?pp=help で確認できる。
---
nana.icon なんかそもそもjsonだけを返してくれるオプションがあるといいんだけど。