# バッチ設計書 8-generate_precompile.jl

## 概要

本ドキュメントは、Juliaプロジェクトにおけるgenerate_precompile.jlバッチスクリプトのバッチ設計書である。システムイメージ生成時にプリコンパイルステートメントを収集・実行し、Juliaの起動時間とパッケージロード時間を短縮するためのビルドプロセスの一部として機能する。

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

このバッチは、Juliaのシステムイメージ（sysimg）生成プロセスにおいて、頻繁に使用されるメソッドのプリコンパイルステートメントを収集・実行するスクリプトである。プリコンパイルされたメソッドはネイティブコードとしてシステムイメージに埋め込まれ、実行時のJITコンパイルコストを削減する。

**業務上の目的・背景**：Juliaは初回実行時にJITコンパイルを行うため、「Time to First Plot」問題として知られる初回実行時のレイテンシが課題となっている。このスクリプトは、Base、標準ライブラリ、REPL、パッケージロードなどで頻繁に使用されるメソッドを事前にプリコンパイルすることで、ユーザーが体感する起動時間と初回実行時間を大幅に短縮する。ビルドプロセスの一部として自動的に実行される重要なバッチである。

**バッチの実行タイミング**：Juliaのビルドプロセス（`make`コマンド実行時）において、システムイメージ生成の一部として自動実行される。手動実行は通常行わない。

**主要な処理内容**：
1. ハードコードされたプリコンパイルステートメント（約140行）の収集
2. Juliaプロセスを起動してprecompileスクリプトを実行し、トレースコンパイル結果を収集
3. パッケージプリコンパイル（__PackagePrecompilationStatementModule）の実行
4. 収集されたステートメントの重複排除とパース
5. PrecompileStagingArea内での各ステートメントの実行（precompile呼び出し）
6. システムイメージの出力

**前後の処理との関連**：本バッチはMakefileのビルドターゲットから呼び出される。No.9 write_base_cache.jl（Baseモジュールのソースキャッシュ生成）とともにビルドプロセスの後半で実行される。システムイメージ（sysimg）の生成が前提条件であり、本スクリプトの出力がシステムイメージに含まれる。

**影響範囲**：生成されるシステムイメージに影響を与える。プリコンパイルの成功/失敗がJuliaの起動パフォーマンスに直接影響する。CI環境ではプリコンパイル失敗時にエラーが発生する。

## バッチ種別

ビルド処理（プリコンパイル最適化）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | ビルド時（随時） |
| 実行時刻 | N/A（ビルドプロセスの一部） |
| 実行曜日 | N/A |
| 実行日 | N/A |
| トリガー | Makefileのビルドターゲット実行 |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Juliaバイナリ | ビルド済みのJuliaバイナリ（julia_exepath()）が利用可能であること |
| システムイメージ | 基本的なシステムイメージ（sysimg）が生成済みであること |
| ARGS条件 | ARGSが空でないか、ARGS[1]が"0"でないこと（"0"の場合はスキップ） |
| シングルスレッド | マルチスレッド環境ではビルドエラーのリスクがある（警告が出る） |

### 実行可否判定

`Base.isempty(Base.ARGS) || Base.ARGS[1] !== "0"`の条件でプリコンパイル処理が実行される。ARGS[1]が"0"の場合は全処理をスキップする。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| ARGS[1] | String | No | N/A | "0"を指定するとプリコンパイルをスキップ |
| PARALLEL_PRECOMPILATION | Bool | No | true | 並列プリコンパイル生成の有効/無効 |
| debug_output | IO | No | devnull | デバッグ出力先（devnullまたはstdout） |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| hardcoded_precompile_statements | String | ハードコードされたプリコンパイルステートメント（約140行） |
| --trace-compile出力 | テキスト | Juliaプロセスのトレースコンパイル結果 |
| Base._included_files | Julia内部 | プリコンパイルトレース中に生成されるファイル |
| Base.loaded_modules | Julia内部 | 読み込み済みモジュール（Artifacts, FileWatching, Libdl） |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| システムイメージ | バイナリ | プリコンパイル済みメソッドを含むsysimg |
| stdout | テキスト | 進捗表示（Collecting and executing precompile statements） |
| stderr | テキスト | 警告メッセージ（プリコンパイル失敗時） |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | システムイメージファイル（ビルドシステム管理） |
| 出力先 | ビルドディレクトリ |
| 文字コード | バイナリ |
| 区切り文字 | N/A |

## 処理フロー

### 処理シーケンス

```
1. 初期化
   ├─ Sys.__init_build()の呼び出し
   ├─ stdio再初期化
   └─ ハードコードされたプリコンパイルステートメントの定義
2. Float型のshow関数プリコンパイル追加
   └─ Float16/Float32/Float64 x IOBuffer/IOContext/TTY/IOContext{TTY}の組み合わせ
3. ロード済みモジュールの追加ステートメント
   ├─ Artifacts用のプリコンパイルステートメント追加
   ├─ FileWatching用のプリコンパイルステートメント追加
   └─ Libdl用のプリコンパイルステートメント追加
4. ステートメント収集フェーズ（Step 1）
   ├─ 一時ディレクトリ作成
   ├─ ダミーパッケージ（__PackagePrecompilationStatementModule）作成
   ├─ Juliaプロセス起動（-O0、--trace-compile、--sysimage指定）
   ├─ プリコンパイルスクリプト実行（REPL操作、パッケージロードなどの模擬）
   └─ トレースコンパイル結果の収集
5. ステートメント実行フェーズ（Step 3）
   ├─ PrecompileStagingAreaモジュールの作成
   ├─ ロード済みモジュールをStagingAreaに登録
   ├─ ステートメントの重複排除（Set使用）
   ├─ 各ステートメントのパースと評価
   └─ precompile()呼び出しによるプリコンパイル実行
6. 後処理
   ├─ GC実行（メモリフットプリント削減）
   ├─ グローバル変数のクリア（PROGRAM_FILE、BINDIR等）
   └─ システムイメージファイルの出力
```

### フローチャート

```mermaid
flowchart TD
    A[スクリプト開始] --> B{ARGS[1] == '0'?}
    B -->|Yes| C[スキップ]
    B -->|No| D[初期化・ハードコードステートメント定義]
    D --> E[ロード済みモジュール用ステートメント追加]
    E --> F[Step 1: ステートメント収集]
    F --> G[Juliaプロセス起動 trace-compile]
    G --> H[トレース結果をChannel経由で収集]
    H --> I[Step 3: ステートメント実行]
    I --> J[PrecompileStagingArea作成]
    J --> K[各ステートメントをパース・実行]
    K --> L{precompile成功?}
    L -->|Yes| M[成功カウント++]
    L -->|No| N[警告出力 or CI時エラー]
    M --> O{全ステートメント処理完了?}
    N --> O
    O -->|No| K
    O -->|Yes| P[GC実行・グローバル変数クリア]
    P --> Q[システムイメージ出力]
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| N/A | N/A | N/A | データベース操作なし |

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

該当なし。本バッチはファイルシステム操作とJulia内部処理のみを行う。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| warning | プリコンパイル失敗 | 個々のステートメントのprecompile()が失敗した場合 | CI環境ではエラーとして処理、ローカルでは警告のみ |
| error | CI環境エラー | CI環境（CI=true）でプリコンパイル失敗した場合 | 失敗したステートメントを確認し修正 |
| warning | 成功数不足 | n_succeeded <= 90（REPLなし）または650（REPLあり） | プリコンパイルスクリプトの見直し |
| error | Step 1失敗 | Juliaプロセスのトレースコンパイルが失敗 | ビルド環境とシステムイメージの状態を確認 |

### リトライ仕様

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

### 障害時対応

プリコンパイル失敗時は、失敗したステートメントの内容をログから確認する。CI環境では明示的にエラーが発生するため、対象ステートメントの修正が必要。ビルド全体を再実行する場合は`make clean && make -j`で対応する。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | N/A |
| コミットタイミング | N/A |
| ロールバック条件 | N/A |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 数百のプリコンパイルステートメント |
| 目標処理時間 | ビルドプロセスの一部として数分以内 |
| メモリ使用量上限 | GC実行（gc(true); gc(false)）でメモリフットプリントを削減 |

## 排他制御

シングルスレッドでの実行が推奨される。`Threads.maxthreadid() != 1`の場合に警告が出力される。ビルドプロセスの一部として1回のみ実行されるため、排他制御は不要。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | 処理開始時 | "Collecting and executing precompile statements" |
| 進捗ログ | 処理中 | Step 1のステートメント数、Step 3の成功/失敗数（アニメーション表示） |
| 完了ログ | 処理完了時 | "Precompilation complete. Summary:" および合計時間 |
| 出力ログ | sysimg出力時 | "Outputting sysimage file..." および出力時間 |
| 警告ログ | 失敗時 | "Failed to precompile expression" |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| プリコンパイル成功数 | 90件（REPLなし）/ 650件（REPLあり） | 標準出力（警告メッセージ） |
| プリコンパイル失敗 | CI環境で1件 | ビルドエラー |

## 備考

- スクリプトは`@eval Base module __precompile_script`ブロック内で実行され、Mainネームスペースを汚染しない
- `PARALLEL_PRECOMPILATION`定数（デフォルト: true）で並列プリコンパイル生成の有無を制御
- `fancyprint`はTTY接続時かつ非CI環境でのみ有効になり、アニメーション付き進捗表示を行う
- 環境変数`JULIA_HISTORY`、`JULIA_LOAD_PATH`、`JULIA_DEPOT_PATH`、`TERM`、`JULIA_FALLBACK_REPL`を設定して子Juliaプロセスを起動
- プリコンパイル対象にはBase、REPL、Artifacts、FileWatching、Libdl、Revise.jl用、Requires.jl用、Precompilation用のメソッドが含まれる
- `Main.`を含むステートメントはスキップされる
- 処理完了後にグローバル変数（PROGRAM_FILE、BINDIR、STDLIB、ARGS等）がクリアされる
