# 性能評価計測計画 (Performance Evaluation Measurement Plan)

## 目的 (Purpose)

3 バージョン（v1.6 / v1.7 / 現行）で性能（主にメモリ挙動，副次的にプレビュー性能）の実験・計測を行い，改善効果を定量・可視化する．結果は研究室共有用に**画面録画＋スライド**で提示することを想定する．

## 対象バージョン (Target Versions)

計測対象は「メモリ改善の 3 段階」を表す．上流（nakaguchi）が素の状態，本 GitHub フォークが改善を積んだ現行．

| 版 | commit | 中身 | 主に効くメモリ経路 |
| --- | --- | --- | --- |
| **v1.6** | `4b107e4`（nakaguchi タグ `v1.6`） | ベースライン | 保存経路・プレビュー経路とも未修正（リークあり） |
| **v1.7** | `5315d2d`（nakaguchi タグ `v1.7`「メモリ使用効率化」） | `SaveThread` が `_shots` から pop して都度 Dispose＋変換行列の中間 Mat 解放 | **保存経路**を改善（プレビューは未修正） |
| **現行** | `HEAD`（GitHub `rintoHasegawa/TIASshot` main） | `ConvertImage` の Mat 解放（メモリ）＋PLAN_03（プレビュー）＋FastClone | **プレビュー経路**を修正＋コピー高速化 |

→ 計測のストーリー: **保存経路は v1.6 → v1.7 で，プレビュー経路は v1.7 → 現行で**効いた，という切り分けを示す．

## 計測手段と役割分担 (Method & Roles)

- **手段**: 実機 MEMMONITOR（メモリ観測ウィンドウ＋プレビュー計測）を使ったライブ計測．自動 NUnit ベンチ（TEST_03）ではなく，**実カメラで普通にアプリを使ったときの挙動**を対象とする．
- **カメラ**: IScam（ImagingSource DFK 23UX249．白板撮影で使用したもの）．
- **役割分担**:
  - **Claude**: 3 本の計装済みビルド（後述の使い捨てブランチ）と実行チェックリストを用意し，出力 CSV を集計して結果ドキュメント（TEST_02）にまとめる．
  - **人間**: 実カメラでの撮影・放置・画面録画を実施する（外部サービス操作・実機動作確認と同じく手動作業）．

### IScam 前提の効き方の違い (Note: IScam)

PLAN_03 で最も派手だった「Lucam のクロススレッド GDI クラッシュ（`_bmps[]` をコールバックスレッドで Dispose）」は **Lucam 固有**で IScam では再現しない．IScam で効くのは次の 5 点であり，計測はここに焦点を当てる．

- `ShowImage` のフルコピー Bitmap リーク（原因1）
- 表示バッファ取りこぼし Dispose（原因2）
- `PreviewMonitor.UpdateImage` 上書き前 Dispose（原因3）
- 副モニタ描画飢餓
- FastClone によるコピー高速化

## 移植方針 (Porting Strategy)

現行の計測スカフォールドを v1.6 / v1.7 に移植して 3 版横並びで計測する．ただし次の制約がある．

- v1.7 は**フラット構成**（`TIASshot/*.cs` 直置き），現行は `UI/`・`Cameras/` 等に**再編済み**のため，cherry-pick は不可．**各タグへ手作業で移植**する．
- 作業は各タグから切った**使い捨てブランチ**（`bench/v1.6`・`bench/v1.7`）上で行い，**`main` には一切マージしない**．
- 移植は結合度で 2 層に分ける（Tier A / Tier B）．
- 移植の原則: 旧版へは**観測フック（カウンタ／Stopwatch）のみ**を足し，**計測対象のロジック（撮影・保存・プレビューのコピー方式・Invalidate タイミング）は一切変えない**．変えると測りたい timing 自体が動く．旧版自体が「修正前」であるため，リーク再現用の仕掛けは不要（旧版をそのまま計測すればよい）．

### Tier A: メモリ観測（低結合・3 版すべてに移植・確定）

`MemoryMonitorForm`（＋`.Designer.cs`）は自前の 500ms タイマーで自プロセスを覗くだけで，計測対象コードに触れない．移植は「2 ファイルを置いて起動時に 1 行で開く」だけで，メモリ挙動を歪めない．

**計測指標（確定）**:

- **主指標: `private_MB`（`Process.PrivateMemorySize64`）** — コミット量．`Mat` はネイティブメモリのため `GC.GetTotalMemory` では捕捉できず，プロセス視点のコミット量を主指標とする．
- 副指標（CSV のみ記録）: `ws_MB`（`WorkingSet64`），`gdi_objects` / `user_objects` / `handle_count`（GDI ハンドル枯渇仮説の否定材料）．

**表示・記録の方針（確定）**:

- **画面グラフは 1 つに，左右 2 軸で描く**（案A）．メモリと FPS は単位・スケールが異なるため軸を分ける（.NET Chart の `Series.YAxisType = Secondary`）．
  - **左 Y 軸（メモリ・GB）**: 主指標 `private_MB` の **1 本のみ**描画する（録画・スライドで「右肩上がり vs 水平」を一目で伝えるため）．現状 2 系列（Private / WorkingSet）を描いているので，WorkingSet 系列は**描かない（または非表示）**にする．
  - **右 Y 軸（副軸・FPS）**: **本モニタ実描画 FPS（M3 `main_paint_fps`）と副モニタ実描画 FPS（M4 `sub_paint_fps`）の 2 本**を折れ線で乗せる．副モニタ飢餓（校正後 ≈2fps → 回復）を録画で線として見せるため（テキスト数値より伝わる）．F9 で副モニタ給餌を ON/OFF して同一録画内で対比する．
  - `callback_fps` 等その他の指標はグラフには乗せず，テキスト（`lblPreview`）と CSV に留める．
- **CSV は全列そのまま残す**（`ws_MB`・ハンドル数はコストゼロの裏取り材料）．「グラフで見せるのはメモリ 1 本＋FPS 2 本，録るのは全部」とする．
- **Y 軸スケールは 3 版で揃える**（現状はオートスケール．バラバラだと「v1.6 も水平」に錯覚するため，録画時に左軸メモリ上限・右軸 FPS 上限を手動で揃えるか，後段でスクショを同スケールで並べる）．
- この FPS オーバーレイは `MemoryMonitorForm` のグラフ描画拡張であり，旧版（`bench/v1.6`・`bench/v1.7`）へ移植する窓にも同じ拡張を含める．

### Tier B: プレビュー性能プロファイラ（高結合・一式移植で確定）

`PreviewProfiler`＋`TimedPictureBox`＋`ShowImage`/`PreviewMonitor` へのフック．旧版はプレビュー経路が別物（`new Bitmap(bmp)` フルコピー・毎フレーム `Invalidate`・タイマー無し）のため，フック位置を各版の `ShowImage` に置き直す必要があり侵襲的．

M1〜M5 は同じスカフォールドに相乗りするため（フックを一度置けば同時取得），指標を個別に間引かず**一式を移植して CSV 全列を記録**する．副モニタ（セカンダリディスプレイ）は実機で**使える**ため，`TimedPictureBox` を要する M4/M5（副モニタ実描画）も計測対象とする．

**計測指標（確定）**:

| # | 指標 | 何がわかるか | 差が出る版 |
| --- | --- | --- | --- |
| M1 | `copy_ms`（1 フレームの Bitmap コピー時間） | FastClone の効果を直接分離（~25ms→~2.5ms） | v1.7 vs 現行 |
| M2 | `callback_fps`（`ShowImage` 呼び出しレート） | コピー負荷がコールバックスレッドを律速しているか | v1.7 vs 現行 |
| M3 | 実効プレビュー FPS（本モニタの実描画レート） | ユーザーに見える滑らかさ（~10→~20fps）．旧版は毎フレーム Invalidate，現行はタイマー駆動のため「結果としての FPS」比較 | v1.7 vs 現行 |
| M4 | 副モニタ描画飢餓（`sub_paint_fps`） | 校正完了後の副モニタ飢餓（≈2fps）と回復（~10fps） | v1.7 vs 現行 |
| M5 | `sub_paint_ms`（副モニタ実描画コスト自体） | 「飢餓 or 描画コスト増」の切り分け | 参考 |
| M6 | GDI/USER/handle 数の推移 | ハンドル枯渇仮説の検証（Tier A の窓が既に保持・移植不要） | v1.7 vs 現行 |

**画面録画・スライドの方針（確定）**: 記録は全指標だが，**録画で強調するのは 2 つの物語**に絞る．

- **① FastClone でコピーが桁で速くなる**: 主役は M1 `copy_ms`（~25ms→~2.5ms），律速の証拠に M2 `callback_fps`．
- **② 副モニタ飢餓の解消**: 主役は M4 副モニタ FPS（v1.7＝校正後に崩壊／現行＝steady），実効 FPS に M3，切り分けに M5．**F9 トグル**（`ToggleSubMonitorProfiling`）で副モニタ給餌の ON/OFF を切り替えながら同一録画内で対比を撮る．

## 計測シナリオ (Scenarios)

同一手順・同一パラメータ（解像度・チャンネル数・枚数・時間）で 3 版を回す．

S1〜S3 は独立に回すのではなく，**現行で実測した 1 本の記録（基準プロトコル）を全版で再現**して同時取得する（副モニタ ON）．基準記録は [docs/06_TEST/data/perf_current.csv](../06_TEST/data/perf_current.csv)．

| ID | 観測対象 | この記録での該当区間 | 主な観測 | 差が出る版 |
| --- | --- | --- | --- | --- |
| **S1** | 保存経路リーク | 撮影イベント前後 | `private_MB` のピーク包絡線 | v1.6 vs v1.7 vs 現行 |
| **S2** | プレビュー経路リーク | 撮影間・放置区間 | `private_MB`＋`gdi_objects`/`handle_count` の推移 | v1.7 vs 現行 |
| **S3** | プレビュー性能 | 全区間（定常プレビュー） | `copy_ms` / `callback_fps` / 実効 FPS / 副モニタ FPS（M1〜M5） | v1.7 vs 現行 |

**基準プロトコル（確定・現行 `perf_current.csv` の秒数に全版を合わせる）**: 撮影は**単発撮影（1 枚撮影）の繰り返し**とする．

- 0〜32 秒: プレビュー放置（副モニタ ON）
- 32.5〜36.1 秒: 校正 1 回（処理時間 約 3.5 秒．アプリ側処理で固定）
- 62 / 92 / 123 秒: 単発撮影（約 30 秒間隔で 3 回）
- 123〜303 秒: プレビュー放置（約 180 秒．S2 のリーク観測区間）
- 303 秒: 単発撮影 1 回
- 約 348 秒: 停止・CSV 保存

旧版（v1.6 / v1.7）もこの**秒数・順序・撮影間隔に合わせて**再現し，同じ時間軸で 3 版を重ねて比較する．

### 同条件の統制 (Comparability Controls)

- 同一マシン・**x64 Debug** ビルド・同一カメラ（IScam）・同一解像度・同一チャンネル数．
- 固定ウォームアップ・固定時間（S1 のサイクル数 M，S2 の放置時間 T を全版共通で固定）．
- **GC を強制しない**（本番のリーク機序を保つ）．
- 観測窓自体もわずかにメモリ・GDI を消費するが，3 版とも同じ overhead のため比較では相殺される．
- CSV はバージョン別に命名して後で重ね描きする．

## 結果の読み方 (Reading the Results)

グラフは滑らかに上がらず**のこぎり波／階段状**になる（OpenCvSharp が GC にメモリ圧を通知し，リーク版でも GC＋ファイナライザが周期的にネイティブメモリを一掃するため）．**見るべきは振れ幅ではなくピーク包絡線のトレンド**（リーク＝右肩上がり／修正済み＝天井一定）．

## 注意点・リスク (Cautions & Risks)

- **実機 OOM 上限**: 自動ベンチ（TEST_03）には打ち切り上限ガードがあったが，実機観測窓（`MemoryMonitorForm`）にはガードが無い（記録するのみ）．S1 でリーク版（v1.6）を長く回すと OOM に達し得るため，**サイクル数 M・放置時間 T に上限を決めておく**（値は計測実施時に確定）．
- **移植の非マージ**: `bench/v1.6`・`bench/v1.7` は計測専用の使い捨てブランチであり，`main` にマージ・push・PR しない．
- 旧版が現行と同じツールチェーン（x64 / .NET Framework 4.8 / OpenCvSharp パッケージ）でビルドできるかは移植着手時に確認する．

## 未確定事項 (Open Items)

- 計測プロトコル・指標は確定．
- 3 版（v1.6 / v1.7 / 現行）の計測・移植・再現計測は**完了**．結果は [TEST_02_性能評価計測結果](../06_TEST/TEST_02_性能評価計測結果.md)．

## 成果物 (Deliverables)

- 本計画: `docs/03_PLAN/PLAN_04_性能評価計測計画.md`．
- 計測結果: `docs/06_TEST/TEST_02_性能評価計測結果.md`（TEST_03 と同形式の 3 版比較表）．

## 関連 (Related)

- ビルドフラグ（`MEMMONITOR`）: [ENV_06_ビルド構成とビルドフラグ](../02_ENV/ENV_06_ビルド構成とビルドフラグ.md)．
- 自動ベンチによるメモリ計測（参考・別手段）: [TEST_03_メモリ修正効果計測](../06_TEST/TEST_03_メモリ修正効果計測.md)．
- プレビューメモリリーク修正の詳細: [PLAN_03_プレビューメモリリーク修正計画](PLAN_03_プレビューメモリリーク修正計画.md)．
</content>
</invoke>
