# 帳票設計書 7-@timevレポート

## 概要

本ドキュメントは、Julia の `@timev` マクロによって出力される詳細パフォーマンス計測レポートの設計仕様を記述する。

### 本帳票の処理概要

本帳票は、Julia の `@timev` マクロにより、`@time` の詳細版として式の実行に関するパフォーマンス情報を複数行で標準出力にレポートする。`@time` の1行サマリーに加え、経過時間（ナノ秒）、GC時間、バイト数、プールアロケーション数、ビッグアロケーション数、malloc/realloc/free 呼び出し数、GC コレクション回数などの詳細カウンターを個別に出力する。

**業務上の目的・背景**：`@time` の1行サマリーでは把握しきれない詳細なメモリアロケーション内訳や GC 動作状況を確認するために、各カウンターの個別値を表示する必要がある。特に、アロケーションがプール経由かビッグアロケーション経由か、malloc/realloc/free の呼び出し回数はどうかなど、メモリ管理の詳細を分析する際に不可欠な情報を提供する。

**帳票の利用シーン**：`@time` で問題が検出された後、より詳細な分析が必要な場合に使用する。特に、アロケーションの種類（プール vs ビッグ）を区別したい場合や、GC コレクションの回数・種類を確認したい場合に利用される。

**主要な出力内容**：
1. `@time` と同じ1行サマリー
2. elapsed time (ns)：経過時間（ナノ秒）
3. gc time (ns)：GC 時間（ナノ秒）
4. bytes allocated：アロケーションバイト数
5. pool allocs：プールアロケーション数
6. non-pool GC allocs：非プール GC アロケーション数（bigalloc）
7. malloc() calls：malloc 呼び出し数（0でない場合）
8. realloc() calls：realloc 呼び出し数（0でない場合）
9. free() calls：free 呼び出し数（malloc > 0 の場合）
10. minor collections：マイナーGCコレクション数
11. full collections：フルGCコレクション数

**帳票の出力タイミング**：`@timev expr` または `@timev "description" expr` が評価されたとき。

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

## 帳票種別

詳細サマリーレポート（複数行形式のパフォーマンス計測結果）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | Julia REPL | julia> | `@timev expr` を実行 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト（標準出力） |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | N/A |
| 出力方法 | 標準出力（stdout）への複数行出力 |
| 文字コード | UTF-8 |

## 帳票レイアウト

### レイアウト概要

`@timev` の出力は、1行目に `@time` と同じサマリー行を出力し、続けて各カウンターの詳細行を出力する。

```
  0.546770 seconds (2.20 M allocations: 116.632 MiB, 4.23% gc time, 99.94% compilation time)
elapsed time (ns): 546769547
gc time (ns):      23115606
bytes allocated:   122297811
pool allocs:       2197930
non-pool GC allocs:1327
malloc() calls:    36
realloc() calls:   5
minor collections: 3
full collections:  0
```

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 表示条件 |
|----|-------|------|-------------|---------|---------|
| 1 | サマリー行 | @time と同じ1行サマリー | `time_print()` | 1行テキスト | 常に表示 |
| 2 | elapsed time (ns) | 経過時間（ナノ秒） | `elapsedtime` | `"elapsed time (ns): {value}"` | 常に表示 |
| 3 | gc time (ns) | GC 時間（ナノ秒） | `diff.total_time` | `"gc time (ns):      {value}"` | 常に表示 |
| 4 | bytes allocated | アロケーションバイト数 | `diff.allocd` | `"bytes allocated:   {value}"` | 常に表示 |
| 5 | pool allocs | プールアロケーション数 | `diff.poolalloc` | `"pool allocs:       {value}"` | 常に表示 |
| 6 | non-pool GC allocs | ビッグアロケーション数 | `diff.bigalloc` | `"non-pool GC allocs:{value}"` | 常に表示 |
| 7 | malloc() calls | malloc 呼び出し数 | `diff.malloc` | `"malloc() calls:    {value}"` | 値が0でない場合のみ |
| 8 | realloc() calls | realloc 呼び出し数 | `diff.realloc` | `"realloc() calls:   {value}"` | 値が0でない場合のみ |
| 9 | free() calls | free 呼び出し数 | `diff.freecall` | `"free() calls:      {value}"` | malloc > 0 の場合のみ |
| 10 | minor collections | マイナーGCコレクション数 | `diff.pause - diff.full_sweep` | `"minor collections: {value}"` | 常に表示 |
| 11 | full collections | フルGCコレクション数 | `diff.full_sweep` | `"full collections:  {value}"` | 常に表示 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| expr | 計測対象の式 | Yes |
| msg | 説明文字列（オプション） | No |

### 改ページ条件

N/A

## データベース参照仕様

`@time` レポートと同一（GC_Num, GC_Diff を使用）。

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| minor collections | `diff.pause - diff.full_sweep` | なし（整数） | pause は GC 一時停止の合計回数 |
| full collections | `diff.full_sweep` | なし（整数） | フルスイープ回数 |
| その他 | `@time` レポートと同一 | - | - |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A["@timev expr 展開"] --> B["@timed expr 実行"]
    B --> C["timev_print() 呼び出し"]
    C --> D["time_print() で1行サマリー出力"]
    D --> E["padded_nonzero_print() で各カウンター出力"]
    E --> F["値を返却"]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 式の実行エラー | 式の評価中に例外が発生 | 元の例外が伝播 | try-finally で計測は完了する |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 1回の計測 |
| 目標出力時間 | ほぼ即座 |
| 同時出力数上限 | N/A |

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

`@timev` の出力にはセキュリティ上の懸念は少ない。

## 備考

- Julia 1.8 以降で説明文字列のオプションが追加された。
- `padded_nonzero_print` は19文字幅でラベルを右パディングし、値を表示する。
- `always_print=false` のパラメータにより、一部の項目は値が0の場合に非表示となる（malloc, realloc）。
- free() calls は malloc > 0 の場合のみ表示される（`diff.malloc > 0` が条件）。

---

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

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

### 推奨読解順序

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

`@time` レポートと共通（GC_Num, GC_Diff 構造体）。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | timing.jl | `base/timing.jl` | `GC_Num`（行4-75）と `GC_Diff`（行80-90）を理解する |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | timing.jl | `base/timing.jl` | `@timev` マクロ（行466-479）で、`@timed` + `timev_print` への展開を理解する |

**主要処理フロー**:
1. **行473**: `@timed expr` を呼び出し
2. **行476**: `timev_print()` を呼び出し

#### Step 3: 出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | timing.jl | `base/timing.jl` | `timev_print()` 関数（行305-322）で詳細出力のロジックを理解する |
| 3-2 | timing.jl | `base/timing.jl` | `padded_nonzero_print()` 関数（行210-215）で行フォーマットを理解する |

**主要処理フロー**:
- **行309**: `time_print()` で1行サマリーを出力
- **行310-311**: elapsed time, gc time を出力
- **行312-313**: bytes allocated, pool allocs を出力
- **行314**: non-pool GC allocs を出力
- **行315-316**: malloc, realloc（0でない場合のみ）
- **行318**: free（malloc > 0 の場合のみ）
- **行319-321**: minor collections, full collections

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

```
@timev msg expr
    |
    +-- @timed expr                         # 計測実行
    |
    +-- timev_print(elapsedtime, diff, lock_conflicts, compile_times)
            |
            +-- time_print(stdout, ...)     # 1行サマリー
            +-- padded_nonzero_print(elapsedtime, "elapsed time (ns)")
            +-- padded_nonzero_print(diff.total_time, "gc time (ns)")
            +-- padded_nonzero_print(diff.allocd, "bytes allocated")
            +-- padded_nonzero_print(diff.poolalloc, "pool allocs")
            +-- padded_nonzero_print(diff.bigalloc, "non-pool GC allocs")
            +-- padded_nonzero_print(diff.malloc, "malloc() calls", false)
            +-- padded_nonzero_print(diff.realloc, "realloc() calls", false)
            +-- padded_nonzero_print(diff.freecall, "free() calls", diff.malloc > 0)
            +-- padded_nonzero_print(minor_collects, "minor collections")
            +-- padded_nonzero_print(diff.full_sweep, "full collections")
```

### データフロー図

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

@timed の NamedTuple ──> timev_print()
    |                         |
    +-- ret.time             +-- time_print()    ──> 1行サマリー
    +-- ret.gcstats          +-- padded_nonzero_print() x N ──> 詳細行
    +-- ret.lock_conflicts
    +-- ret.compile_time
    +-- ret.recompile_time
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| timing.jl | `base/timing.jl` | ソース | @timev マクロ、timev_print、padded_nonzero_print、time_print、GC_Num、GC_Diff |
