3 バージョン(v1.6 / v1.7 / 現行)で性能(主にメモリ挙動,副次的にプレビュー性能)の実験・計測を行い,改善効果を定量・可視化する.結果は研究室共有用に画面録画+スライドで提示することを想定する.
計測対象は「メモリ改善の 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) | PLAN_02(ConvertImage)+PLAN_03(プレビュー)+FastClone | プレビュー経路を修正+コピー高速化 |
→ 計測のストーリー: 保存経路は v1.6 → v1.7 で,プレビュー経路は v1.7 → 現行で効いた,という切り分けを示す.
PLAN_03 で最も派手だった「Lucam のクロススレッド GDI クラッシュ(_bmps[] をコールバックスレッドで Dispose)」は Lucam 固有で IScam では再現しない.IScam で効くのは次の 5 点であり,計測はここに焦点を当てる.
ShowImage のフルコピー Bitmap リーク(原因1)PreviewMonitor.UpdateImage 上書き前 Dispose(原因3)現行の計測スカフォールドを v1.6 / v1.7 に移植して 3 版横並びで計測する.ただし次の制約がある.
TIASshot/*.cs 直置き),現行は UI/・Cameras/ 等に再編済みのため,cherry-pick は不可.各タグへ手作業で移植する.bench/v1.6・bench/v1.7)上で行い,main には一切マージしない.LEAKY_REPRO は不要(旧版自体が「修正前」であるため).MemoryMonitorForm(+.Designer.cs)は自前の 500ms タイマーで自プロセスを覗くだけで,計測対象コードに触れない.移植は「2 ファイルを置いて起動時に 1 行で開く」だけで,メモリ挙動を歪めない.
計測指標(確定):
private_MB(Process.PrivateMemorySize64) — コミット量.Mat はネイティブメモリのため GC.GetTotalMemory では捕捉できず,プロセス視点のコミット量を主指標とする.ws_MB(WorkingSet64),gdi_objects / user_objects / handle_count(GDI ハンドル枯渇仮説の否定材料).表示・記録の方針(確定):
Series.YAxisType = Secondary).
private_MB の 1 本のみ描画する(録画・スライドで「右肩上がり vs 水平」を一目で伝えるため).現状 2 系列(Private / WorkingSet)を描いているので,WorkingSet 系列は**描かない(または非表示)**にする.main_paint_fps)と副モニタ実描画 FPS(M4 sub_paint_fps)の 2 本を折れ線で乗せる.副モニタ飢餓(校正後 ≈2fps → 回復)を録画で線として見せるため(テキスト数値より伝わる).F9 で副モニタ給餌を ON/OFF して同一録画内で対比する.callback_fps 等その他の指標はグラフには乗せず,テキスト(lblPreview)と CSV に留める.ws_MB・ハンドル数はコストゼロの裏取り材料).「グラフで見せるのはメモリ 1 本+FPS 2 本,録るのは全部」とする.MemoryMonitorForm のグラフ描画拡張であり,旧版(bench/v1.6・bench/v1.7)へ移植する窓にも同じ拡張を含める.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 つの物語に絞る.
copy_ms(25ms→2.5ms),律速の証拠に M2 callback_fps.ToggleSubMonitorProfiling)で副モニタ給餌の ON/OFF を切り替えながら同一録画内で対比を撮る.同一手順・同一パラメータ(解像度・チャンネル数・枚数・時間)で 3 版を回す.
S1〜S3 は独立に回すのではなく,現行で実測した 1 本の記録(基準プロトコル)を全版で再現して同時取得する(副モニタ ON).基準記録は docs/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 枚撮影)の繰り返しとする.
旧版(v1.6 / v1.7)もこの秒数・順序・撮影間隔に合わせて再現し,同じ時間軸で 3 版を重ねて比較する.
グラフは滑らかに上がらずのこぎり波/階段状になる(OpenCvSharp が GC にメモリ圧を通知し,リーク版でも GC+ファイナライザが周期的にネイティブメモリを一掃するため).見るべきは振れ幅ではなくピーク包絡線のトレンド(リーク=右肩上がり/修正済み=天井一定).
MemoryMonitorForm)にはガードが無い(記録するのみ).S1 でリーク版(v1.6)を長く回すと OOM に達し得るため,サイクル数 M・放置時間 T に上限を決めておく(値は計測実施時に確定).bench/v1.6・bench/v1.7 は計測専用の使い捨てブランチであり,main にマージ・push・PR しない.docs/03_PLAN/PLAN_04_性能評価計測計画.md.docs/06_TEST/TEST_02_性能評価計測結果.md(TEST_01 と同形式の 3 版比較表).MEMMONITOR / LEAKY_REPRO): ENV_06_ビルド構成とビルドフラグ.