# バッチ設計書 14-rake benchmark

## 概要

本ドキュメントは、mrubyプロジェクトにおけるベンチマークテストの実行と結果のグラフ生成を行う`rake benchmark`タスクのバッチ設計書である。

### 本バッチの処理概要

`rake benchmark`は、mrubyのベンチマークテスト（benchmark/bm_*.rb）を各ビルドターゲットに対して複数回実行し、実行時間を計測してgnuplotを用いてグラフ（PNGファイル）を生成するRakeタスクである。各ベンチマークはMRuby::BENCHMARK_REPEAT（4回）ずつ実行され、user時間とsys時間の平均・最小・最大が記録される。

**業務上の目的・背景**：mrubyの実行パフォーマンスを定量的に計測・可視化するために必要なタスクである。コード変更がパフォーマンスに与える影響を検出し、パフォーマンス回帰を防止する目的で使用される。ビルド設定ごとの性能比較も可能である。

**バッチの実行タイミング**：開発者による手動実行。パフォーマンスに影響する変更を行った際や、リリース前のパフォーマンス検証時に実行される。定常的なCI/CDでの自動実行は行われていない。

**主要な処理内容**：
1. benchmark_enabled?が有効なビルドターゲットを抽出
2. 各ターゲットのmrubyバイナリを使用してベンチマークスクリプト（bm_*.rb）を実行
3. 各ベンチマークを4回（BENCHMARK_REPEAT）繰り返し実行し、timeコマンドでreal/user/sys時間を計測
4. user+sys時間の平均値を算出し、.datファイルに記録
5. gnuplotを使用して全ベンチマーク結果をヒストグラムとしてPNGファイルに出力

**前後の処理との関連**：mrubyバイナリのビルドが完了している必要がある（build/{target}/bin/mrubyへの依存）。前提タスクとして暗黙的にビルドタスクが実行される。後続処理はなく、結果はグラフとして出力される。

**影響範囲**：benchmark/ディレクトリ配下に.datファイルとPNGグラフファイルが生成される。ソースコードやビルド成果物には影響しない。

## バッチ種別

ベンチマーク実行・レポート生成

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時 |
| 実行時刻 | 任意 |
| 実行曜日 | 該当なし |
| 実行日 | 該当なし |
| トリガー | 手動実行 |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Ruby実行環境 | Rubyインタプリタがインストールされていること |
| Rakeインストール | Rakeがインストールされていること |
| mrubyバイナリ | 各ターゲットのmrubyバイナリがビルド済みであること |
| gnuplot | gnuplotがインストールされていること（グラフ生成に必要） |
| timeコマンド | POSIX timeコマンド（time -p）が利用可能であること |
| ベンチマーク有効化 | ビルド設定でbenchmark_enabled?がtrueであること |

### 実行可否判定

ビルドターゲットの`benchmark_enabled?`がtrueかつ`internal?`がfalseのターゲットのみが対象となる。対象ターゲットが存在しない場合、plot関数内で「no build target to benchmark against」エラーが発生する。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| MRUBY_CONFIG | 環境変数/文字列 | No | build_config/default.rb | ビルド設定ファイルのパス |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| benchmark/bm_*.rb | Ruby(mruby) | ベンチマークスクリプトファイル群 |
| benchmark/plot.gpl | gnuplot | gnuplotの描画設定ファイル |
| build/{target}/bin/mruby | バイナリ | 各ターゲットのmruby実行バイナリ |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| benchmark/{config_name}/{target_name}/*.dat | テキスト | 各ベンチマークの計測結果データ |
| benchmark/{config_name}.png | PNG画像 | ベンチマーク結果のヒストグラムグラフ |
| 標準出力 | テキスト | 実行進捗と結果出力パスの表示 |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名（dat） | bm_{ベンチマーク名}.dat |
| ファイル名（グラフ） | {build_config_name}.png |
| 出力先 | benchmark/ディレクトリ配下 |
| 文字コード | UTF-8 |
| datファイル形式 | `{ベンチマーク名} {平均値} {最小値} {最大値}`（スペース区切り） |

## 処理フロー

### 処理シーケンス

```
1. ビルドターゲットの走査
   └─ benchmark_enabled?かつ!internal?のターゲットを選択
2. 各ターゲットごとにベンチマーク実行
   └─ benchmark/bm_*.rbファイルをglob取得
3. 各ベンチマークスクリプトの実行（4回繰り返し）
   └─ `time -p {mruby_bin} {bm_file}` で実行時間計測
   └─ real/user/sys時間を取得
4. 計測結果の集計
   └─ (user + sys) / 2 の平均・最小・最大を算出
5. .datファイルへの出力
   └─ 「ベンチマーク名 平均 最小 最大」形式で書き込み
6. gnuplotによるグラフ生成
   └─ plot.gplの設定を読み込み
   └─ ヒストグラムをPNGとして出力
```

### フローチャート

```mermaid
flowchart TD
    A[rake benchmark 開始] --> B[ターゲット走査]
    B --> C{benchmark_enabled? かつ !internal?}
    C -->|Yes| D[bm_*.rb ファイル取得]
    C -->|No| E[スキップ]
    D --> F[ベンチマークスクリプト実行 x4回]
    F --> G[time -p で実行時間計測]
    G --> H[user+sys時間の平均/最小/最大算出]
    H --> I[.dat ファイル出力]
    I --> J{次のベンチマークあり?}
    J -->|Yes| F
    J -->|No| K{次のターゲットあり?}
    K -->|Yes| C
    K -->|No| L[gnuplot でグラフ生成]
    L --> M[PNG ファイル出力]
    M --> N[完了メッセージ出力]
    E --> K
```

## データベース操作仕様

### 操作別データベース影響一覧

本バッチはデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | ターゲット不在 | benchmark_enabled?がtrueのターゲットが存在しない | ビルド設定でベンチマークを有効化する |
| N/A | gnuplot未インストール | gnuplotが見つからない場合 | gnuplotをインストールする |
| N/A | mrubyバイナリ未生成 | ビルドが完了していない場合 | rake allでビルドを完了させる |
| N/A | ベンチマーク実行エラー | ベンチマークスクリプトの実行に失敗した場合 | スクリプトの内容を確認し修正 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（手動再実行） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

### 障害時対応

ベンチマーク実行に失敗した場合は、mrubyバイナリの状態とベンチマークスクリプトを確認する。gnuplotのグラフ生成に失敗した場合は、gnuplotのインストール状態とplot.gplファイルの存在を確認する。

## トランザクション仕様

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | N/A（ファイル出力のみ） |
| コミットタイミング | N/A |
| ロールバック条件 | N/A |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | ベンチマークファイル数 x ターゲット数 x 4回 |
| 目標処理時間 | ベンチマーク内容に依存（数分〜数十分） |
| メモリ使用量上限 | 特に制限なし |

## 排他制御

同一ベンチマーク出力ディレクトリに対する同時実行は想定されていない。ベンチマーク計測中は他のCPU負荷の高いプロセスが結果に影響する可能性があるため、可能な限り単独実行が推奨される。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 進捗ログ | 各ベンチマーク開始時 | ベンチマーク名の表示（例：bm_fib...） |
| 結果ログ | グラフ生成完了時 | 「Benchmark results output to {path}」 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 処理時間 | ベンチマーク依存 | 手動確認 |

## 備考

- ベンチマーク結果のデータファイルは `benchmark/{config_name}/{target_name}/bm_{name}.dat` に保存される
- 現在のベンチマークファイルは bm_ao_render.rb、bm_app_lc_fizzbuzz.rb、bm_fib.rb、bm_mandel_term.rb、bm_so_lists.rb、bm_so_mandelbrot.rb の6つ
- BENCHMARK_REPEATは4回に固定されている（MRuby::BENCHMARK_REPEAT = 4）
- 計測値は (user + sys) / 2 で算出される（real時間は使用されない）
- グラフはPNGcairo形式で1400x1024ピクセル、Sans 8ptフォントで出力される
- グラフのスタイルはヒストグラム（エラーバー付き）
