# 帳票設計書 6-ベンチマーク結果

## 概要

本ドキュメントは、フォーマット処理のパフォーマンス計測結果をJSON形式で出力する帳票「ベンチマーク結果」の設計仕様を定義する。

### 本帳票の処理概要

**業務上の目的・背景**：Prettierのパフォーマンス最適化や、プラグイン開発時のパフォーマンス検証において、フォーマット処理の実行時間を正確に計測することが重要である。本帳票は、tinybenchライブラリを使用した高精度なベンチマーク結果を提供し、開発者がパフォーマンスのボトルネックを特定したり、最適化の効果を検証したりすることを可能にする。

**帳票の利用シーン**：Prettier本体のパフォーマンス最適化、プラグイン開発時のパフォーマンステスト、異なる設定間でのパフォーマンス比較、CI/CDでのパフォーマンス回帰テストなど。

**主要な出力内容**：
1. 実行回数（ops/sec）
2. 平均実行時間（ms）
3. 最小/最大実行時間
4. 標準偏差

**帳票の出力タイミング**：CLIで`--debug-benchmark`オプションを指定した際に出力される。また、`--debug-repeat`オプションや`PRETTIER_PERF_REPEAT`環境変数でも類似の計測が可能。

**帳票の利用者**：Prettier開発者、プラグイン開発者、パフォーマンスエンジニア

## 帳票種別

デバッグ出力（JSON）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| CLI-01 | コマンドライン | `prettier --debug-benchmark <file>` | コマンド実行 |
| CLI-02 | コマンドライン | `prettier --debug-repeat <count> <file>` | コマンド実行 |
| ENV-01 | 環境変数 | `PRETTIER_PERF_REPEAT=N prettier <file>` | コマンド実行 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | JSON（--debug-benchmark） / テキスト（--debug-repeat） |
| 出力先 | 標準エラー出力（debug log） |
| 文字コード | UTF-8 |
| フォーマット | 整形済みJSON |

### JSON構造（--debug-benchmark）

```json
{
  "Task Name": "Format",
  "ops/sec": "123.45",
  "Average Time (ns)": 8000000,
  "Margin": "±0.50%",
  "Samples": 100
}
```

### JSON構造（--debug-repeat）

```json
{
  "repeat": 10,
  "hz": 125.0,
  "ms": 8.0
}
```

## 帳票レイアウト

### レイアウト概要

出力はベンチマーク結果を含むJSONオブジェクト。

```
┌─────────────────────────────────────┐
│  [debug] ベンチマーク設定メッセージ     │
├─────────────────────────────────────┤
│  [debug] 計測結果JSON                │
│  {                                   │
│    "Task Name": "Format",            │
│    "ops/sec": "...",                 │
│    "Average Time (ns)": ...,         │
│    ...                               │
│  }                                   │
└─────────────────────────────────────┘
```

### 出力項目（--debug-benchmark）

| No | 項目名 | 説明 | 型 | 備考 |
|----|-------|------|-----|------|
| 1 | Task Name | タスク名 | string | 固定: "Format" |
| 2 | ops/sec | 1秒あたりの実行回数 | string | 数値文字列 |
| 3 | Average Time (ns) | 平均実行時間（ナノ秒） | number | |
| 4 | Margin | 誤差範囲 | string | ±パーセント表示 |
| 5 | Samples | サンプル数 | number | 実行回数 |

### 出力項目（--debug-repeat）

| No | 項目名 | 説明 | 型 | 備考 |
|----|-------|------|-----|------|
| 1 | repeat | 繰り返し回数 | number | 指定回数 |
| 2 | hz | 1秒あたりの実行回数 | number | 計算値 |
| 3 | ms | 平均実行時間（ミリ秒） | number | 計算値 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| 入力ファイル | ベンチマーク対象のファイル | Yes |
| --debug-benchmark | tinybench使用フラグ | No |
| --debug-repeat | 繰り返し回数指定 | No |
| PRETTIER_PERF_REPEAT | 環境変数での繰り返し回数 | No |

### 処理条件

| 条件 | 処理 |
|------|------|
| tinybench未インストール | エラーメッセージ出力、exit(2) |
| performanceTestFlag設定時 | コード出力スキップ |

## データフロー仕様

### 入力データ

| データ項目 | 型 | 説明 |
|-----------|-----|------|
| input | string | フォーマット対象のソースコード |
| opt | object | フォーマットオプション |
| context.argv.debugBenchmark | boolean | ベンチマークフラグ |
| context.argv.debugRepeat | number | 繰り返し回数 |

### 出力データ

| データ項目 | 型 | 説明 |
|-----------|-----|------|
| benchmarkResult | object | ベンチマーク結果 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[format関数] --> B{performanceTestFlag?}
    B -->|debugBenchmark| C[tinybenchインポート]
    C --> D{インポート成功?}
    D -->|No| E[エラー出力 & exit]
    D -->|Yes| F[Benchインスタンス作成]
    F --> G[bench.add Format]
    G --> H[bench.run]
    H --> I[bench.table取得]
    I --> J[JSON.stringify]
    J --> K[logger.debug出力]
    B -->|debugRepeat| L[開始時刻記録]
    L --> M[repeat回フォーマット実行]
    M --> N[終了時刻記録]
    N --> O[平均時間計算]
    O --> P[結果JSON生成]
    P --> K
```

### ベンチマーク実行フロー

```mermaid
flowchart TD
    A[Bench初期化] --> B[bench.add]
    B --> C[タスク登録: prettier.formatWithCursor]
    C --> D[bench.run]
    D --> E[ウォームアップ実行]
    E --> F[計測実行]
    F --> G[統計計算]
    G --> H[テーブル形式結果生成]
    H --> I[結果返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| モジュール未インストール | tinybenchがない | '--debug-benchmark' requires the 'tinybench' package to be installed. | npm install tinybench |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 処理方式 | 非同期処理（async/await） |
| 計測ライブラリ | tinybench（オプション） |
| 時間計測 | mockable.getTimestamp（高精度） |

## セキュリティ考慮事項

- デバッグ出力のためプロダクション環境での使用は非推奨
- 出力にはソースコードの処理時間が含まれるが、コード内容は含まれない

## 備考

- tinybenchはオプションの依存関係であり、必要時にのみインストール
- --debug-repeatはより簡易な計測方法
- PRETTIER_PERF_REPEAT環境変数は正規表現`/^\d+$/`でバリデーション
- performanceTestFlag設定時はコード出力をスキップ（計測のみ実行）

---

## コードリーディングガイド

本帳票を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、ベンチマーク結果の構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | context.js | `src/cli/context.js` | performanceTestFlagゲッター（58-85行目） |

**読解のコツ**: performanceTestFlagは3種類の指定方法（--debug-benchmark, --debug-repeat, 環境変数）を統一的に扱う。

#### Step 2: エントリーポイントを理解する

ベンチマーク処理のトリガーを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | format.js | `src/cli/format.js` | format関数内のperformanceTestFlag処理（161-208行目） |

**主要処理フロー**:
1. **161行目**: performanceTestFlag取得
2. **162行目**: debugBenchmark判定
3. **163-183行目**: tinybenchを使用したベンチマーク
4. **184-208行目**: --debug-repeat処理

#### Step 3: tinybenchベンチマーク処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | format.js | `src/cli/format.js` | tinybenchインポートと実行（163-183行目） |

**主要処理フロー**:
- **164-171行目**: tinybenchの動的インポートとエラー処理
- **172-177行目**: ベンチマーク設定と実行
- **179-183行目**: 結果の取得と出力

#### Step 4: --debug-repeat処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | format.js | `src/cli/format.js` | 繰り返し処理と計測（184-208行目） |

**主要処理フロー**:
- **185行目**: 繰り返し回数取得
- **189行目**: 開始時刻記録
- **190-192行目**: 指定回数フォーマット実行
- **193-198行目**: 結果計算（hz, ms）
- **199-207行目**: 結果出力

#### Step 5: 環境変数処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | context.js | `src/cli/context.js` | PRETTIER_PERF_REPEAT処理（77-84行目） |

**主要処理フロー**:
- **77行目**: 環境変数取得
- **78行目**: 数値バリデーション（正規表現）
- **79-83行目**: フラグオブジェクト生成

### プログラム呼び出し階層図

```
CLI: format() [src/cli/format.js:102]
    │
    ├─ context.performanceTestFlag [src/cli/context.js:58]
    │      │
    │      ├─ debugBenchmark判定
    │      ├─ debugRepeat判定
    │      └─ PRETTIER_PERF_REPEAT判定
    │
    ├─ (debugBenchmark時)
    │      │
    │      ├─ import("tinybench") [動的インポート]
    │      │
    │      ├─ new Bench()
    │      │
    │      ├─ bench.add("Format", formatWithCursor)
    │      │
    │      ├─ bench.run()
    │      │
    │      └─ bench.table() → logger.debug()
    │
    └─ (debugRepeat時)
           │
           ├─ mockable.getTimestamp() [開始]
           │
           ├─ prettier.formatWithCursor() × N回
           │
           ├─ mockable.getTimestamp() [終了]
           │
           └─ 結果計算 → logger.debug()
```

### データフロー図

```
[入力]                    [処理]                         [出力]

ソースコード ──────────▶ format()
                              │
                              ▼
                    performanceTestFlag判定
                              │
                    ┌─────────┴─────────┐
                    │                   │
               debugBenchmark      debugRepeat
                    │                   │
                    ▼                   ▼
              tinybench.Bench    ループ実行 × N
                    │                   │
                    ▼                   ▼
              bench.table()      時間計算
                    │                   │
                    ▼                   ▼
              JSON結果 ─────────────────────▶ logger.debug()
                                                    │
                                                    ▼
                                              標準エラー出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| format.js | `src/cli/format.js` | ソース | ベンチマーク処理実装 |
| context.js | `src/cli/context.js` | ソース | performanceTestFlagゲッター |
| mockable.js | `src/cli/mockable.js` | ソース | getTimestamp関数 |
| logger.js | `src/cli/logger.js` | ソース | debug出力 |
| tinybench (npm) | node_modules/tinybench | 外部ライブラリ | ベンチマーク実行 |
