起動時間の計測
CAT_STARTUP_TRACE に出力先を指定すると、起動処理の各時点をCSVに記録する。
未指定なら記録しない。計測の有無で起動順序や自動演奏の条件は変わらない。
PowerShellでリポジトリのルートから実行する例(Releaseビルド済みの場合):
$env:CAT_STARTUP_TRACE = Join-Path (Get-Location) 'target/startup.csv'
try {
& ./target/release/cat-plugin-player.exe
} finally {
Remove-Item Env:CAT_STARTUP_TRACE
}
Get-Content ./target/startup.csv
出力先の親ディレクトリは事前に作成する。同名ファイルは上書きする。 通常は最初の信号生成と背景走査の両方が完了した後のUI更新で保存する。未完了なら10秒経過後の UI更新、または正常終了時に途中までの結果を保存する。 UIスレッドが停止している間やプロセスが強制終了された場合は保存できない。 各計測点はプロセス中の初回のみを記録するため、比較にはアプリを起動し直す。
- 基準はRustの
main()入口。Windowsのプロセス生成・DLLロードなど、それ以前の時間は含まない。 scan_callbackは走査完了通知がメインスレッドへ届いた時点。走査処理と通知待ちを含む。load_call_returnedとinstance_callbackにより、生成API呼び出し自体と完了通知までを分ける。gui_requestedからapp_creationがeframeのGUI初期化区間。first_audio_callbackは音声コールバック開始、first_signal_renderedは絶対値が 0.000001(-120 dBFS)を超えるサンプルを初めて生成したブロックの処理後。 スピーカーからの発音時刻や、耳で聞こえる音量に達した時刻ではない。- 音声スレッドでは時刻の取得とatomicへの記録だけを行い、ファイルI/OはUI側で行う。 信号検出のサンプル検査は計測有効時だけ行い、信号を検出した後は行わない。
- 未到達の計測点は
# missing:に記載する。失敗の詳細は通常の画面表示・標準エラーを確認する。
2026-10-06の変更前の結果
Windows、Release版、履歴のSurge XT(CLAP、org.surge-synth-team.surge-xt)を自動復元。
同一環境で3回連続起動。OSのキャッシュを消す操作は行っていないため、コールド起動の保証はない。
計測ログは target/startup-profiles/run-1.csv ~ run-3.csv(git管理外)。
| 区間(ms) | 1回目 | 2回目 | 3回目 |
|---|---|---|---|
| main → App生成開始(GUI等の初期化) | 241.529 | 238.973 | 248.787 |
| App生成開始 → 走査要求(ホスト・デバイス・履歴) | 9.056 | 8.582 | 8.459 |
| 走査要求 → 完了通知 | 603.173 | 553.046 | 561.187 |
| 完了通知 → ロード要求(一覧取得・履歴照合) | 0.016 | 0.015 | 0.028 |
| ロード要求 → 生成完了通知 | 522.077 | 509.006 | 512.885 |
| 生成完了通知 → 最初の信号生成 | 24.077 | 19.816 | 20.045 |
| main → 最初の信号生成 | 1399.928 | 1329.438 | 1351.391 |
主な待ち時間は走査とプラグイン生成。生成API呼び出し自体が507~520msを占め、 そこから生成完了通知までの待ちは約2msだった。 音声ストリーム構築は約19~23ms、デバイス照会は約8ms。
次の改善候補は、前回の1件を直接生成し、全体走査を発音後へ移すこと。 現在の経路から走査時間だけを差し引くと約0.78~0.80秒になるが、これは計算上の参考値であり、 変更後の実測値ではない。直接生成の追加コスト、プラグインロードのキャッシュ状況、 背景走査との競合などで変わる。
さらに短縮する場合は約0.24秒のGUI初期化より前に必要な音声準備を始める構成を検討する。 プラグインのメインスレッド要件は維持する。 観測された「exe起動から約2秒」との差は今回の計測だけでは特定できず、 OSローダーや実際の出力遅延を含めた別の計測が必要。
GUI・全体走査を発音後に移した結果
同じRelease版・Surge XTで再計測。旧履歴からの移行起動を1回行った後、3回連続で起動。
ログは target/startup-profiles/fast-1.csv ~ fast-3.csv。
| mainからの経過時間(ms) | 1回目 | 2回目 | 3回目 |
|---|---|---|---|
| 最初の信号生成 | 597.676 | 557.234 | 556.114 |
| GUI初期化開始 | 598.771 | 558.094 | 556.704 |
| GUIのApp生成 | 843.759 | 786.714 | 785.376 |
| 背景走査開始 | 846.643 | 789.756 | 788.521 |
| 一覧取得完了 | 1415.557 | 1347.672 | 1413.321 |
信号生成の中央値は1351.391msから557.234msへ、約794ms(59%)短縮した。 これは連続起動での比較であり、OSキャッシュを消したコールド起動の結果ではない。 一覧取得が完了する前から演奏できる。GUI初期化は同じメインスレッド上で発音後に行い、 描画器を別スレッドへ移したわけではない。
起動時は保存したバンドルパス・形式・ID・表示情報から1件だけ生成する。 旧形式の履歴、ファイル消失、直接生成失敗時はGUIを開き、走査後に形式・IDで復元を試す。 成功した演奏の履歴にはバンドルパスも保存されるため、旧形式からは通常1回の起動で移行する。
GUI生成前にはshimタスクとWindowsメッセージを処理し、最初の音声コールバックが 処理を終えるのを待つ。無音の音色でもGUIを止めないよう、非ゼロ信号自体は待たない。 非同期の生成・音声開始を待つループは2秒でGUIへ引き継ぐ。 プラグイン内部の同期呼び出しが長時間ブロックする場合は、この制限では中断できない。 GUI初期化中のメインスレッド要求は初期化後に処理されるため、全プラグインでの互換性を 保証するものではない。
背景走査用のホストと、各演奏インスタンスのカタログ情報・形式オブジェクトを分離した。 一覧更新による参照切れや、古いパスを保持した形式キャッシュの再利用を防ぐ。 プラグインの生成・UI・破棄は引き続き同じメインスレッドで行う。
検証: cargo fmt --check、cargo clippy --all-targets -- -D warnings、cargo test、
cargo build --release。実機の補助確認は python tests/native_startup_smoke.py。
後者はPython 3.11以降と、演奏・UI表示ができるインストール済み音源の新形式の履歴を必要とする。
音声はメモリ上で生成し、エディタを一度開閉する。履歴ファイルは変更しない。
欠落パス・生成失敗、演奏中の2回の一覧再取得、再ロード、エディタ開閉、削除、
走査中の終了を確認する(強制フルスキャンは行わない)。
アプリ本体でも、保存パスを一時的に存在しないパスへ変更し、通常走査→ロード→信号生成と 履歴パスの修復を確認した。検証終了後は元の履歴ファイルを復元済み。