swift-concurrency-performance について
Swift Concurrency のパフォーマンスを調査する開発者向けのレビュー用スキルです。非同期境界とタスクの所有者を確認し、応答性やキャンセルなどの問題に対する小規模な変更と検証方法を提案します。
主な機能
- 01タスクのライフタイムと構造化並行処理の確認
- 02MainActor のボトルネックと Actor 競合の分析
- 03キャンセル、ストリーム、Continuation の点検
- 04非同期コンテキスト内のブロッキング処理の特定
- 05Instruments などを使った検証計画
活用シーン
- 01非同期処理による UI 停滞の調査
- 02画面遷移後も残るタスクやリークの追跡
- 03Actor キューの滞留や重複リクエストの診断
- 04AsyncStream のクリーンアップとバッファリングの確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ livsy90/ ios-performance-agent-skills --skill swift-concurrency-performanceインストール後、Claude Code で/swift-concurrency-performanceを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlreferences/actor-reentrancy.mdasyncsequence-and-stream-cleanup.mdblocking-legacy-apis.mdbounded-task-groups.mdcancellation-and-task-lifetime.mdconcurrency-runtime.mdcontinuation-safety.mddiagnostics-and-instruments.mdmainactor-responsiveness.mdswift-6-isolation.mdtask-lifetime-and-structure.md詳細
Swift Concurrency のパフォーマンス
目的
非同期処理が UI の応答性、スループット、メモリ、キャンセル、タスクのライフタイム、アクターの競合、負荷時の正確性に影響する場合に、Swift Concurrency のコードをレビュー、診断、改善するためにこのスキルを使用します。
このスキルは、Swift Concurrency の一般的なチュートリアルではありません。パフォーマンスと応答性をレビューするワークフローです。
このスキルを使用する場面
次のようなタスクを扱う場合に、このスキルを使用してください。
- 非同期処理に関連する UI の停止、応答の遅延、ハング、フレーム落ち;
Taskの過剰な作成、タスクグループ、デタッチされたタスク、非構造化並行処理;MainActorのボトルネック、アクター間の切り替え、アクターキューの滞留、アクターの競合;- 処理を停止できないキャンセル、ナビゲーションに伴うリーク、所有者より長く存続するタスク;
AsyncSequence、AsyncStream、長時間実行されるストリーム、バッファリング、プロデューサーのクリーンアップ;- 継続のブリッジ、デリゲート/コールバックのラッパー、レガシー API を囲む非同期ラッパー;
- 非同期コンテキスト内のブロッキング呼び出し、セマフォ、同期 I/O、ロック、協調型スレッドプールの枯渇;
- アクターのリエントランシー、実行中処理の重複、キャッシュスタンピード、
await後の一貫性のないアクター状態; - Swift 6 の分離動作、明示的な分離、
@concurrent、nonisolated、Sendable の境界; - 並行処理に関連する遅延、メモリ増加、スループット低下を示す Instruments のトレース、ログ、本番環境のシグナル。
このスキルを使用しない場面
次の場合は、このスキルを使用しないでください。
- パフォーマンス、ライフタイム、応答性に関する懸念がない、基本的な
async/await構文の質問; - 並行処理がクリティカルパスに含まれない、一般的なアーキテクチャの議論;
- 非同期のライフサイクル処理が症状に関係しない、SwiftUI の描画だけに関する問題;
- 非同期の起動処理、タスクのライフタイム、アクター分離が起動パスに含まれない、起動パフォーマンスの問題;
- 並行処理の動作に関係しない、ランタイムレベルの割り当て、ARC、ジェネリクス、存在型のコスト;
- タスクが Swift Concurrency のパフォーマンスパターンに特化したものでない、サーバーサイドの並行処理に関する質問。
より具体的な領域がタスクの中心となる場合は、別のスキルを優先してください。
- アプリの起動、初回フレーム、初回操作、pre-main、dyld、SDK の起動処理には
ios-launch-performanceを使用してください; - SwiftUI の無効化、アイデンティティ、レイアウト、スクロール、body のコストには
swiftui-performanceを使用してください; - 主なタスクがプロファイリングツールの選択や解釈である場合は、
ios-performance-profilingを使用してください; - 割り当て、ARC のトラフィック、ディスパッチ、存在型、ジェネリクス、コピーオンライトのコストには
swift-runtime-performanceを使用してください。
中核となるワークフロー
- ユーザーに見える症状を特定します。UI の停止、応答の遅延、スループットの低下、メモリの増加、処理の重複、タスクのリーク、キャンセルの取りこぼし、アクターの競合、協調型スレッドのブロックなどです。
- 非同期境界を特定します。
Task、タスクグループ、アクターメソッド、MainActor、継続、ストリーム、ライフサイクルコールバック、デリゲートブリッジ、レガシーのブロッキング API などです。 - ライフタイムの所有者を特定します。ビュー、ビューモデル、サービス、アクター、リクエスト、アプリセッション、ストリームのコンシューマー、デタッチされたバックグラウンドプロセスなどです。
- 必須の処理と、任意または後回しにできる処理を切り分けます。
- 並行処理が、漠然としたパフォーマンス向上策ではなく、構造、分離、キャンセルを表現するために使われているかを確認します。
- 非同期コンテキスト内にブロッキング処理がないか確認します。
- UI の状態に影響する処理が適切な範囲で分離されているか、CPU 負荷の高い処理がメインアクター上で実行されていないかを確認します。
- 特にタスクグループ、ストリーム、継続、ループ、ナビゲーションのライフタイムをまたいで、キャンセルが伝播するか確認します。
- アクター分離されたメソッド内の各
awaitの後に、アクターのリエントランシーを確認します。 - ライフタイム、キャンセル、分離、スループットを改善する、最小限で安全な変更を提案します。
- 変更をパフォーマンス改善と呼ぶ前に、検証方法を示します。
判断ルール
asyncは中断として扱い、自動的なバックグラウンド実行とはみなさないでください。- 並行処理によってパフォーマンスが向上するとは限りません。タスクを増やすと、スケジューリングのオーバーヘッド、メモリ負荷、アクターの競合、キャンセルの複雑さが増す可能性があります。
- 作業のライフタイムを親が管理する場合は、構造化並行処理を優先してください。
- 非構造化タスクは、ライフタイムを意図的に独立させ、キャンセルの所有者を明確にする場合にのみ使用してください。
Task.detachedは、継承されるコンテキスト、優先度、タスクローカル値、アクター分離から明示的に抜け出す場合にのみ使用してください。- 入力サイズが増える可能性がある場合は、並列処理の量に上限を設けてください。
MainActor上の処理は短く保ち、UI 状態、表示の調整、メインスレッド専用 API に集中させてください。- CPU 負荷の高い処理はメインアクターの分離の外に移してください。ただし、分離境界を安易にまたがないでください。
- 頻繁なホップが遅延の主因となるホットパスでは、アクター呼び出しをまとめてください。
- アクター内の
awaitの後は、アクターの状態が変わっている可能性があると考えてください。 - 原則としてチェック付き継続を使用し、すべての経路で継続がちょうど 1 回再開されることを確認してください。
- ストリームの終了とプロデューサーのクリーンアップも、API 契約の一部として扱ってください。
- 長時間または大量の処理を行う場合は、キャンセルに対応したループやパイプラインを優先してください。
- パフォーマンスに関する主張には、必ず根拠または検証計画を示してください。
注意点
- コードが遅いという理由だけで、
asyncやTaskの追加を推奨しないでください。 - API や UI 状態がメインアクター上に分離されている必要がある場合は、処理を
MainActorの外に移さないでください。 - UI 状態も所有しているというだけの理由で、CPU 負荷の高い計算を
@MainActor型に残さないでください。 - 分離エラーを黙らせるために
Task.detachedを使わないでください。使用する場合は、ライフタイム、キャンセル、優先度、データの安全性への影響を説明してください。 - 並行数を制限せずに、大規模または上限のないコレクションの各要素に対して子タスクを 1 つずつ作成しないでください。
- 広範な
catchブロックでキャンセルを握りつぶさないでください。 - 親タスクをキャンセルすれば、レガシーなコールバック、ストリーム、デリゲート、または手動で保持されたプロデューサーも自動的に停止するとは限りません。
- 基盤となる処理が協調型エグゼキューターのスレッドをブロックしたままなら、ブロッキング API を
asyncでラップしないでください。 - キャッシュミス時にアクターメソッドがサスペンドする場合、アクター分離によって重複作業が防止されるとは考えないでください。
- チェック付き継続のオーバーヘッドが問題であることをプロファイリングで確認し、再開契約が証明されていない限り、非安全な継続を使用しないでください。
- 最適化の前後で検証せずに、最適化が成功したと判断しないでください。
参照資料の使い分け
関連する場合にのみ、以下を参照してください。
references/concurrency-runtime.md— タスク、一時停止、協調型エグゼキューター、アクターのエグゼキューター、優先順位、構造化並行処理、または非同期コードをブロックすることが有害な理由についての概念モデルが必要な場合に参照してください。references/mainactor-responsiveness.md— タスクにMainActor、@MainActor型、UI の状態、ビューモデル、メインスレッドの停止、@concurrent、または CPU 負荷の高い処理を UI の隔離領域から移動することが含まれる場合に参照してください。references/task-lifetime-and-structure.md— タスクに構造化並行処理、非構造化タスク、タスクの所有権、Task {}、Task.detached、ビュー/ビューモデルのライフタイム、または所有者より長く存続するタスクが含まれる場合に参照してください。references/cancellation-and-task-lifetime.md— タスクに画面遷移時のキャンセル、長時間実行される処理、キャンセルの伝播、catchによるキャンセルの握りつぶし、タスクグループ、ストリーム、またはキャンセルのテストが含まれる場合に参照してください。references/bounded-task-groups.md— タスクにwithTaskGroup、withThrowingTaskGroup、並列マッピング、ファンアウト処理、メモリ使用量の急増、または並行数の制限が含まれる場合に参照してください。references/actor-reentrancy.md— タスクにアクターで隔離された状態、重複するネットワークリクエスト、キャッシュの集中アクセス、awaitの前後での状態確認、またはアクターキューの滞留が含まれる場合に参照してください。references/swift-6-isolation.md— タスクに Swift 6 の隔離動作、デフォルトのアクター隔離、@concurrent、nonisolated、Sendable の境界、または移行に関連するパフォーマンスの低下が含まれる場合に参照してください。references/blocking-legacy-apis.md— タスクにセマフォ、同期的なファイル I/O、ブロッキングネットワーキング、ロック、コールバック API、古い SDK、またはブロッキング処理をラップする非同期処理が含まれる場合に参照してください。references/continuation-safety.md— タスクにwithCheckedContinuation、withCheckedThrowingContinuation、デリゲートのブリッジ、コールバックラッパー、タイムアウト時の経路、キャンセル時の経路、または一度だけ再開する保証が含まれる場合に参照してください。references/asyncsequence-and-stream-cleanup.md— タスクにAsyncSequence、AsyncStream、AsyncThrowingStream、長時間稼働するストリーム、バッファリング、プロデューサーのライフタイム、onTermination、またはfor awaitループが含まれる場合に参照してください。references/diagnostics-and-instruments.md— ユーザーがトレース、ログ、測定値、本番環境のシグナルを提示した場合、または並行処理に関連するパフォーマンスの変化を検証する方法を尋ねた場合に参照してください。
検証の指針
疑われる問題に応じた検証を推奨してください。
- 症状が UI の停止、アクターの競合、タスクのライフタイム、ブロックされたスレッド、またはタスク数の多さに関係する場合は、Instruments を使用してください。
- 非同期境界をまたぐ前後のレイテンシーを比較する場合は、サインポストを使用してください。
- 画面遷移、解放、タイムアウト、または親タスクのキャンセル後に処理を停止すべき場合は、キャンセルのテストを行ってください。
- ストリーム、タスクグループ、または長時間存続するタスクが、プロデューサーや大きな値を保持している可能性がある場合は、メモリグラフまたは割り当て計測ツールを使用してください。
- 同時実行中の処理の重複を確認する場合は、タスク ID またはリクエスト ID を含むログを使用してください。
- ワークロードを十分に再現でき、意味のある比較が可能な場合に限り、XCTest のパフォーマンステストを使用してください。
- ローカルのトレースではテールレイテンシーやまれに発生するタスクの停止を再現できない場合は、本番環境のメトリクスを使用してください。
明確な検証方法を示さずに、並行処理のリファクタリングをパフォーマンス向上策として提示しないでください。
出力の要件
コードをレビューする際は、次の内容を回答してください。
- 指摘事項 — 並行処理のパフォーマンス、ライフタイム、分離、または応答性に関する問題の可能性。
- 重要な理由 — UI のレイテンシー、スループット、メモリ、キャンセル、アクターの競合、または正確性への影響。
- 根拠 — コードのパターン、トレースの兆候、ライフサイクルの不一致、キャンセル経路の欠落、ブロッキング呼び出し、アクターのホップパターン、または継続/ストリームの契約に関する問題。
- 推奨する変更 — まずは安全で最小限の変更を提案してください。設計自体に問題がない限り、大規模な書き換えは避けてください。
- トレードオフ — 変更によって改善される点と、複雑になる可能性がある点。
- 検証方法 — Instruments、サインポスト、キャンセルテスト、ログ、メモリツール、UI の挙動、または本番環境のメトリクスを使って、結果を検証する方法。
調査計画を求められた場合は、次の内容を回答してください。
- 再現する症状。
- 疑わしい非同期境界。
- ライフタイムまたは分離の管理主体。
- 最初に収集するトレースまたはログ。
- 仮説を肯定または否定するシグナル。
- 次に調査する最小限のコード領域。
説明を求められた場合は、実践的な内容にしてください。
- モデルを簡潔に説明する。
- 必要な場合に限り、iOS または Swift の具体例を1つ示す。
- よくある誤解を挙げる。
- 検証方法またはデバッグ手法を含める。 :::
コメント
Markdown 対応