mcpField
I
instruments-analyzer

instruments-analyzer

github.com/jlreyes開発3554 回インストール21 週間前に更新
リポジトリ

instruments-analyzer について

Apple Instruments の `.trace` データを DuckDB に書き出し、SQL で性能を分析するスキルです。CPU 使用状況や SwiftUI の更新、アニメーションのカクつき、ハングを調べる開発者向けに、フレーム単位の分析手順も備えています。

主な機能

  1. 01Instruments のトレースを DuckDB に出力
  2. 02CPU と SwiftUI の性能データを検索
  3. 03カクつきとハングの分析
  4. 04フレーム分析用ビューの作成
  5. 05関連ログを使った原因の追跡

活用シーン

  1. 01バックトレースから CPU のホットスポットを特定
  2. 02SwiftUI のスクロールやアニメーションのカクつきを診断
  3. 03アプリのハングや無応答を調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jlreyes/instruments-analyzer --skill instruments-analyzer

インストール後、Claude Code で/instruments-analyzerを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

SCHEMAS.md
scroll_and_animation.md
.gitignore
LICENSE
README.md
PerfDebugging.tracetemplate
.github/workflows/
tests.yml
scripts/
prepare_analysis.py
export_to_duckdb.py
tests/
test_export_to_duckdb.py
tests/fixtures/
time_profile_dedup.xml

詳細

Instruments Analyzer

このツールを使うと、Apple Instruments のトレースデータにプログラムからアクセスできます。Instruments は通常 GUI ツールですが、このツールは .trace ファイルを DuckDB にエクスポートし、SQL でクエリできるようにします。


このツールを使用する場面

  • Instruments の .trace ファイルがある、または記録したい場合
  • CPU プロファイリング、ヒッチ、ハング、サインポスト、Core Animation、SwiftUI の更新、RunLoop のアクティビティなど、パフォーマンスデータを分析したい場合
  • フレーム単位またはイベント単位の根拠に基づいて根本原因を分析したい場合

スクロールやアニメーションのカクつきの診断:scroll_and_animation.md を参照してください。操作区間の特定、ドロップフレームの順位付け、カスケード分析、フレームごとの帰属分析、優先順位付きの修正計画の作成を行う、フレームを起点としたワークフローです。


ワークフローの概要

  1. 記録:トレースを記録します(または既存のものを使用します)
  2. エクスポート:トレースを DuckDB にエクスポートします
  3. 調査:エクスポートしたテーブルを調べます
  4. 準備:派生ビューを準備します(任意。フレーム単位の分析向け)
  5. 分析:DuckDB データベースに対して SQL クエリを実行します

手順 1:トレースを記録する

xctrace を使ってコマンドラインから記録します。

# Attach to a running app
xcrun xctrace record --template 'SwiftUI' --time-limit 20s \
  --output ./traces/recording.trace \
  --attach AppName --no-prompt

# Or launch the app
xcrun xctrace record --template 'SwiftUI' --time-limit 20s \
  --output ./traces/recording.trace \
  --launch /path/to/App.app --no-prompt

Instruments に含まれている PerfDebugging.tracetemplate も使用できます。

テンプレートの選択
  • SwiftUI:SwiftUI ビューの更新、ヒッチ、Core Animation、サインポスト
  • Time Profiler:バックトレース付きの CPU サンプリング
  • Animation Hitches:フレームのライフタイム、ヒッチの検出
  • Custom:必要に応じてインストゥルメントを組み合わせます

xcrun xctrace list templates を実行すると、利用可能なテンプレートを確認できます。


手順 2:DuckDB にエクスポートする

エクスポートスクリプトは、Instruments の .trace ファイルを、Parquet を基盤とする DuckDB データベースに変換します。

./scripts/export_to_duckdb.py traces/recording.trace traces/recording/analysis.duckdb

スクリプトの動作:

  • shebang 経由で uv run を使用するため、直接実行してください(python3 では実行しないでください)
  • uv が必要です
  • 出力先のパスに親ディレクトリが存在しない場合は作成します
  • Instruments の各テーブルを圧縮された Parquet ファイルとしてエクスポートします
  • Parquet ファイルを参照するビューを含む DuckDB データベースを作成します

エクスポート後に主要なテーブルが空の場合は、別の Instruments テンプレートを使用するか、記録時間を長くするよう提案してください。


手順 3:エクスポートしたテーブルを調べる

エクスポート後、DuckDB データベースに接続し、利用可能なデータを確認します。

-- List all tables/views
SHOW TABLES;

-- Check row counts
SELECT 'updates' AS tbl, COUNT(*) AS rows FROM updates
UNION ALL SELECT 'hitches', COUNT(*) FROM hitches
UNION ALL SELECT 'time_profile', COUNT(*) FROM time_profile
UNION ALL SELECT 'os_signpost_intervals', COUNT(*) FROM os_signpost_intervals
UNION ALL SELECT 'runloop_intervals', COUNT(*) FROM runloop_intervals
UNION ALL SELECT 'potential_hangs', COUNT(*) FROM potential_hangs;
主なテーブル
テーブル内容
updates個々の SwiftUI ビューの body 評価
update_groupsバッチ化された SwiftUI トランザクショングループ
hitches検出されたアニメーションのヒッチ(フレーム落ち)
hitches_frame_lifetimesフレームのライフタイムデータ全体
hitches_updates / hitches_renders / hitches_gpu / hitches_framewaitフェーズごとのフレームデータ
time_profileバックトレース付きの CPU サンプリング
os_signpost_intervalsサインポストの区間(開始/終了のペア)
os_signpostサインポストのポイントイベント
os_logos_log からのログメッセージ
runloop_intervalsRunLoop のアクティビティ(メインスレッドのスケジューリング)
coreanimation_context_intervalsCA のレンダリングフェーズ(Layout、Display、Prepare、Commit)
coreanimation_lifetime_intervals許容レイテンシのしきい値を含む CA フレームのライフタイム
potential_hangs検出されたハングと応答不能状態
life_cycle_periodsアプリのライフサイクルの遷移
swiftui_causesSwiftUI の依存関係/因果関係グラフ
swiftui_changesバックトレース付きの SwiftUI 変更イベント

スキーマの完全なリファレンス:SCHEMAS.md

よく使う調査クエリ
-- Signpost overview (what instrumentation exists)
SELECT
  name, category, subsystem,
  COUNT(*) AS n,
  MAX(CAST(duration_ns AS BIGINT))/1e6 AS max_ms
FROM os_signpost_intervals
WHERE name IS NOT NULL
GROUP BY 1,2,3
ORDER BY max_ms DESC
LIMIT 50;
-- Worst hitches
SELECT start_ns/1e9 AS time_s, duration_ns/1e6 AS ms, narrative_description
FROM hitches
ORDER BY duration_ns DESC
LIMIT 20;
-- Heaviest CPU backtraces
SELECT
  COUNT(*) AS samples,
  SUM(weight_ns)/1e6 AS approx_ms,
  backtrace_json
FROM time_profile
WHERE backtrace_json IS NOT NULL
GROUP BY backtrace_json
ORDER BY approx_ms DESC
LIMIT 10;
-- Hang summary
SELECT hang_type, COUNT(*) AS count, MAX(duration_ns)/1e6 AS max_ms
FROM potential_hangs
GROUP BY hang_type
ORDER BY max_ms DESC;

手順 4:派生ビューを準備する(フレーム分析用)

prepare_analysis.py スクリプトは、エクスポートした生データを基に、分析に適したビューを作成します。

./scripts/prepare_analysis.py traces/recording/analysis.duckdb

このスクリプトは hitches_frame_lifetimes から frames ビューを作成し、以下を含めます。

  • 算出された missed_frames の数
  • 深刻度の分類(Low/Medium/High/Extreme)
  • coreanimation_lifetime_intervals.acceptable_latency_ns から推定したフレーム予算
  • 値を取得できない場合は 60fps(16.67ms)を使用

120fps ディスプレイの場合は、次のように上書きします。

./scripts/prepare_analysis.py traces/recording/analysis.duckdb --budget-ms 8.33
フレーム固有のカスケード分析

周辺のコンテキストとともに、特定のフレームを分析します。

./scripts/prepare_analysis.py traces/recording/analysis.duckdb --swap-id 166871
./scripts/prepare_analysis.py traces/recording/analysis.duckdb --swap-id 166871 --context-frames 10

次の情報が出力されます。

  • 対象フレームの詳細
  • 予算ステータスを含む先行フレーム
  • 根本原因の特定(カスケード内で最初に予算を超過したフレーム)
  • 根本原因となったフレーム中のサインポストとログ

時間単位

  • すべてのタイムスタンプと継続時間の単位はナノ秒です。
  • start_ns はトレース開始からの相対値です(実時間ではありません)。
  • 変換方法:ミリ秒は duration_ns / 1e6、秒は start_ns / 1e9 です。
  • os_signpost_* のタイムスタンプは文字列です。比較する際は BIGINT にキャストしてください。

ユースケース向け関連リソース

コメント