# バッチ設計書 14-benchmark

## 概要

本ドキュメントは、webpackプロジェクトにおけるnpm script `benchmark` の処理内容、実行条件、入出力仕様、エラー処理等を定義するバッチ設計書である。

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

`benchmark` は、webpackのビルドパフォーマンスを測定するベンチマーク実行バッチである。V8エンジンの最適化を無効化した確定的（deterministic）な実行環境を構築し、`test/BenchmarkTestCases.benchmark.mjs` を起動して、ベンチマークケースごとに複数のシナリオ（development、development-rebuild、production）でビルド性能を計測する。tinybenchライブラリによる統計的な測定と、CodSpeed連携によるCI上でのパフォーマンス追跡を実現する。

**業務上の目的・背景**：webpackはビルドツールとしてパフォーマンスが重要な品質指標である。コード変更がビルド性能に与える影響を定量的に評価するために、ベンチマーク機構が必要である。本バッチにより、HEADコミットとBASEコミットのビルド性能を比較し、パフォーマンス退行を検出する。CIパイプラインではCodSpeedと連携してパフォーマンストラッキングを行う。

**バッチの実行タイミング**：CI/CDパイプラインでのPR作成・更新時、およびパフォーマンス確認が必要な場合に手動実行する。

**主要な処理内容**：
1. V8フラグ検証 - 必要なV8フラグ（`--no-opt`、`--predictable`等）が設定されているか確認
2. ベースラインリビジョン取得 - git履歴からHEADとBASEのリビジョンを特定
3. ベースライン環境構築 - BASEリビジョンのwebpackソースコードをチェックアウト
4. ベンチマークケース検索 - `test/benchmarkCases/` ディレクトリからベンチマークケースを列挙
5. ベンチマーク登録 - 各ケース x 各シナリオ x 各ベースラインの組み合わせでベンチマークタスクを登録
6. ベンチマーク実行 - tinybenchでウォームアップ（2回）後、本測定（8回）を実行
7. 統計解析 - t分布による信頼区間の算出、ベースライン間の性能比較

**前後の処理との関連**：テストスクリプト（`test`）とは独立したベンチマーク専用のスクリプトである。`test/benchmarkCases/` 配下にベンチマークケースが定義され、各ケースは `webpack.config.mjs` でビルド設定を保持する。CodSpeed連携時は `@codspeed/core` パッケージを使用する。

**影響範囲**：`test/js/benchmark/` ディレクトリにビルド出力が生成される。プロファイリング有効時（`PROFILE`環境変数設定時）は `test/js/benchmark/profiles/` にCPUプロファイルが出力される。`test/js/benchmark-baselines/` にBASEリビジョンのソースコードがチェックアウトされる。プロジェクトのソースコード自体は変更しない。

## バッチ種別

パフォーマンスベンチマーク / 性能測定

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時 |
| 実行時刻 | 任意 |
| 実行曜日 | 該当なし |
| 実行日 | 該当なし |
| トリガー | CI/CDパイプライン（PRチェック時）、手動実行（`yarn benchmark`） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Node.js 10.13.0以上 | package.jsonのenginesフィールドによる要件 |
| npm依存関係インストール済み | tinybench、@codspeed/core、simple-git等が必要 |
| gitリポジトリ | ベースラインリビジョン取得にgit操作が必要 |
| test/benchmarkCases/ | ベンチマークケースが存在する必要がある |
| V8フラグ対応 | Node.jsが--no-opt、--predictable等のV8フラグに対応している必要がある |

### 実行可否判定

前提条件が全て満たされていれば実行可能。`FILTER`環境変数でベンチマーク対象をフィルタリング可能。`SHARD`環境変数でベンチマークを分割実行可能。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| LAST_COMMIT | 環境変数 | No | undefined | 設定するとHEADのみベンチマーク（ベースライン比較なし） |
| PROFILE | 環境変数 | No | undefined | 設定するとCPUプロファイルを生成 |
| HEAD | 環境変数 | No | git rev-listから自動取得 | HEADリビジョンの手動指定 |
| BASE | 環境変数 | No | git rev-listから自動取得 | BASEリビジョンの手動指定 |
| FILTER | 環境変数 | No | undefined | ベンチマークケース名のフィルタ（正規表現） |
| NEGATIVE_FILTER | 環境変数 | No | undefined | ベンチマークケース名の除外フィルタ（正規表現） |
| SHARD | 環境変数 | No | "1/1" | シャード指定（"パート/総数" 形式、例: "1/3"） |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| test/benchmarkCases/ | ディレクトリ | ベンチマークケース群（各サブディレクトリ） |
| test/benchmarkCases/*/webpack.config.mjs | ESModule | 各ベンチマークケースのwebpack設定 |
| test/benchmarkCases/*/options.mjs | ESModule | ベンチマークケースのオプション設定（任意） |
| test/benchmarkCases/*/index.bench.mjs | ESModule | ユニットベンチマークの場合のベンチマーク定義 |
| .git/ | Git | リビジョン履歴（ベースライン取得用） |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| test/js/benchmark/ | ディレクトリ | webpackビルド出力（各ケース x シナリオ x ベースライン） |
| test/js/benchmark-baselines/ | ディレクトリ | BASEリビジョンのwebpackソースコード |
| test/js/benchmark/profiles/ | ディレクトリ | CPUプロファイル（PROFILE環境変数設定時のみ） |
| 標準出力 | テキスト | ベンチマーク結果（統計情報、性能比較） |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | {sanitized-bench-name}-{timestamp}.cpuprofile（プロファイリング時） |
| 出力先 | test/js/benchmark/profiles/ |
| 文字コード | UTF-8（JSON形式） |
| 区切り文字 | JSON形式 |

## 処理フロー

### 処理シーケンス

```
1. V8フラグ検証
   └─ 必要なV8フラグ（--no-opt、--predictable等）が設定されているか確認
2. ベースラインリビジョン取得
   ├─ git rev-list でHEADの親コミットを取得
   ├─ HEAD/BASE環境変数が設定されている場合はそれを使用
   └─ LAST_COMMIT設定時はHEADのみ
3. ベースライン環境構築
   ├─ BASEリビジョンのディレクトリ存在確認
   ├─ 存在しない場合はgit reset --hardでチェックアウト
   └─ 元のHEADとインデックスを復元
4. ベンチマークケース検索
   ├─ test/benchmarkCases/ からサブディレクトリを列挙
   ├─ FILTER/NEGATIVE_FILTER でフィルタリング
   ├─ SHARDで分割
   └─ ロングベンチマーク（-long付き）を均等に分散配置
5. ベンチマーク登録
   ├─ ユニットベンチマーク（-unit付き）: index.bench.mjsを読み込み
   └─ 通常ベンチマーク: 各シナリオ（development/development-rebuild/production）x 各ベースラインで登録
6. ベンチマーク実行（tinybench）
   ├─ ウォームアップ: 2イテレーション
   ├─ 本測定: 8イテレーション
   └─ watchシナリオ: ファイル変更をシミュレートしてリビルド性能を測定
7. 統計解析・結果出力
   ├─ 平均、標準偏差の算出
   ├─ t分布による90%信頼区間の算出
   └─ HEAD vs BASE の性能比較（faster/slower/same）
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[V8フラグ検証]
    B --> C[ベースラインリビジョン取得]
    C --> D{LAST_COMMIT設定?}
    D -->|Yes| E[HEADのみ使用]
    D -->|No| F[HEAD + BASE取得]
    E --> G[ベースライン環境構築]
    F --> G
    G --> H[ベンチマークケース検索<br>FILTER/SHARD適用]
    H --> I[ベンチマーク登録<br>ケース x シナリオ x ベースライン]
    I --> J[ベンチマーク実行<br>ウォームアップ2回 + 本測定8回]
    J --> K[統計解析<br>t分布信頼区間算出]
    K --> L[結果出力<br>性能比較]
    L --> M[バッチ正常終了]
```

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

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

本バッチはデータベース操作を行わない。

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 該当なし | 該当なし | 該当なし | 該当なし |

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| Error | V8フラグ不足 | 必要なV8フラグが未設定 | npm script経由で実行（フラグが自動設定される） |
| Error | リビジョン取得失敗 | git rev-listの結果が不正 | gitリポジトリの状態を確認 |
| Error | ベースライン構築失敗 | git reset --hardが失敗 | .gitディレクトリの整合性を確認 |
| Error | ビルドエラー | webpackビルドが失敗（エラーまたは警告） | ベンチマークケースのwebpack設定を確認 |
| Error | SHARD値不正 | SHARD環境変数の形式が不正 | "パート/総数" 形式で指定（例: "1/3"） |
| Error | ベンチマーク数不足 | SHARDの総数がベンチマーク数を超過 | SHARD値を調整 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし。ただしtinybenchが内部でウォームアップを実行） |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

### 障害時対応

ビルドエラーの場合は、該当するベンチマークケースのwebpack設定を確認する。ベースライン構築の失敗はgitリポジトリの状態に起因することが多いため、`test/js/benchmark-baselines/` ディレクトリを削除して再実行する。tinybenchの `throws: true` 設定により、ベンチマーク中のエラーは即座にスローされる。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | 該当なし（データベース操作なし） |
| コミットタイミング | 該当なし |
| ロールバック条件 | 該当なし |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | ベンチマークケース数 x シナリオ数（3） x ベースライン数（1-2） x イテレーション数（8+2ウォームアップ） |
| 目標処理時間 | ベンチマークケース数に依存（数十分〜数時間） |
| メモリ使用量上限 | 4096MB（--max-old-space-size=4096） |

## 排他制御

同一プロジェクトディレクトリ内での同時実行は推奨されない。ベースライン構築時にgitのインデックスを一時的に変更するため、他のgit操作と競合する可能性がある。`SHARD`環境変数による分割実行はCI環境での並列実行を想定しているが、各シャードは独立した環境で実行する必要がある。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 警告ログ | V8フラグ不足時 | `Missing required flags: ...` |
| 進捗ログ | ベンチマーク登録時 | `Register: benchmark "{test}", scenario '...' {baseline} ({rev})` |
| 進捗ログ | セットアップ/ティアダウン時 | `Setup ({mode} mode): {task}` / `Teardown ({mode} mode): {task}` |
| 計測ログ | 各イテレーション前後 | `Time ({mode} mode): {benchName}` （console.time/timeEnd） |
| 結果ログ | 各サイクル完了時 | `Cycle: {name} {mean} +/- {sd} [{min}; {max}] ({runs} runs sampled)` |
| 比較ログ | ベースライン比較時 | `Result: ... is {percent}% {faster/slower/same} than ...` |
| CodSpeedログ | CodSpeed有効時 | `[CodSpeed] running with @codspeed/tinybench ({mode} mode)` |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| プロセス終了コード | != 0 | CI/CDパイプライン |
| パフォーマンス退行 | 信頼区間の重複なし（統計的有意差あり） | CodSpeed / CI結果 |
| 実行時間 | CIタイムアウト値 | CI/CDパイプライン |

## 備考

- Node.jsの実行フラグとして `--max-old-space-size=4096 --experimental-vm-modules --trace-deprecation --hash-seed=1 --random-seed=1 --no-opt --predictable --predictable-gc-schedule --interpreted-frames-native-stack --allow-natives-syntax --expose-gc --no-concurrent-sweeping` が設定される。これらは測定の再現性を確保するためのV8最適化無効化フラグである。
- tinybenchの設定: `warmup: true`、`warmupIterations: 2`、`iterations: 8`、`throws: true`、`now: hrtimeNow`（高精度タイマー）。
- シナリオは3種類: `mode-development`（開発モードビルド）、`mode-development-rebuild`（開発モードウォッチ・リビルド）、`mode-production`（本番モードビルド）。
- watchシナリオ（`mode-development-rebuild`）では、エントリファイルに書き込みを行いリビルドをトリガーする。`beforeAll` で初回ビルドを行い、本測定ではファイル変更後のリビルド時間のみを計測する。
- `LAST_COMMIT` 環境変数設定時はHEADのみのベンチマークとなり、ベースライン比較は行わない。
- 統計解析にはStudent's t分布（90%信頼区間、両側検定）を使用する。サンプル数に応じたt値テーブルが組み込まれている。
- CodSpeed連携時は `simulation`、`memory`、`walltime` の3つのランナーモードに対応する。
