instruments-analyzer について
Apple Instruments の `.trace` データを DuckDB に書き出し、SQL で性能を分析するスキルです。CPU 使用状況や SwiftUI の更新、アニメーションのカクつき、ハングを調べる開発者向けに、フレーム単位の分析手順も備えています。
主な機能
- 01Instruments のトレースを DuckDB に出力
- 02CPU と SwiftUI の性能データを検索
- 03カクつきとハングの分析
- 04フレーム分析用ビューの作成
- 05関連ログを使った原因の追跡
活用シーン
- 01バックトレースから CPU のホットスポットを特定
- 02SwiftUI のスクロールやアニメーションのカクつきを診断
- 03アプリのハングや無応答を調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jlreyes/ instruments-analyzer --skill instruments-analyzerインストール後、Claude Code で/instruments-analyzerを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
SCHEMAS.mdscroll_and_animation.md.gitignoreLICENSEREADME.mdPerfDebugging.tracetemplate.github/workflows/tests.ymlscripts/prepare_analysis.pyexport_to_duckdb.pytests/test_export_to_duckdb.pytests/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 を参照してください。操作区間の特定、ドロップフレームの順位付け、カスケード分析、フレームごとの帰属分析、優先順位付きの修正計画の作成を行う、フレームを起点としたワークフローです。
ワークフローの概要
- 記録:トレースを記録します(または既存のものを使用します)
- エクスポート:トレースを DuckDB にエクスポートします
- 調査:エクスポートしたテーブルを調べます
- 準備:派生ビューを準備します(任意。フレーム単位の分析向け)
- 分析: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_log | os_log からのログメッセージ |
runloop_intervals | RunLoop のアクティビティ(メインスレッドのスケジューリング) |
coreanimation_context_intervals | CA のレンダリングフェーズ(Layout、Display、Prepare、Commit) |
coreanimation_lifetime_intervals | 許容レイテンシのしきい値を含む CA フレームのライフタイム |
potential_hangs | 検出されたハングと応答不能状態 |
life_cycle_periods | アプリのライフサイクルの遷移 |
swiftui_causes | SwiftUI の依存関係/因果関係グラフ |
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 にキャストしてください。
ユースケース向け関連リソース
- scroll_and_animation.md — SwiftUI のスクロールおよびアニメーションのカクつきの診断