# 通知設計書 40-プロファイルバッファ満杯警告

## 概要

本ドキュメントは、プロファイルデータバッファが満杯になり、プロファイリングが途中で中断された可能性がある場合に出力される警告通知の設計を記述する。

### 本通知の処理概要

本通知は、`Profile.fetch` 関数でプロファイルデータを取得する際に、プロファイルバッファが満杯であることが検出された場合にワーニングレベルのログを出力する処理である。

**業務上の目的・背景**：Julia のプロファイラーはサンプリングされたバックトレース情報を固定サイズのメモリバッファに蓄積する。バッファが満杯になると、新しいサンプルの記録が停止し、プロファイリングが完全でなくなる。本通知はこの状況をユーザーに知らせ、より大きなバッファを設定するか、より短い時間でプロファイリングを実行するよう案内するために設けられている。

**通知の送信タイミング**：`fetch` 関数内で `is_buffer_full()` が `true` を返し、かつ `limitwarn` パラメータが `true`（デフォルト）の場合に送信される。具体的には `stdlib/Profile/src/Profile.jl` の693-695行目で発火する。

**通知の受信者**：Julia プロセスの標準エラー出力 (stderr) を監視する開発者。ログレベルは `Warn`。

**通知内容の概要**：`"The profile data buffer is full; profiling probably terminated before your program finished. To profile for longer runs, call Profile.init() with a larger buffer and/or larger delay."` という複数行の警告メッセージが出力される。

**期待されるアクション**：開発者は `Profile.init(n=<大きな値>)` でバッファサイズを増やすか、`Profile.init(delay=<大きな値>)` でサンプリング間隔を広げることで、プロファイリング対象の全期間をカバーできるようにする。

## 通知種別

ログ（Warn） -- Julia の標準ログシステム（`@warn` マクロ）による stderr への警告レベル出力

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（`@warn` マクロによる即座のログ出力） |
| 優先度 | 中 |
| リトライ | 無し |

### 送信先決定ロジック

Julia の標準ログシステムにより、現在アクティブなログハンドラに送信される。

## 通知テンプレート

### メール通知の場合

該当なし（本通知はログ出力であり、メール送信は行わない）

### 本文テンプレート

```
The profile data buffer is full; profiling probably terminated
before your program finished. To profile for longer runs, call
`Profile.init()` with a larger buffer and/or larger delay.
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| （なし） | 本通知は固定文字列のみ | -- | -- |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| プロファイルデータ取得 | `Profile.fetch()` の呼び出し | `is_buffer_full()` が `true` かつ `limitwarn == true` | `fetch` 関数内の条件分岐で検出 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| バッファが満杯でない | `is_buffer_full()` が `false` の場合、本通知は発生しない |
| `limitwarn = false` | 明示的に警告が無効化された場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A["Profile.fetch(; limitwarn=true) 呼び出し"] --> B["maxlen = maxlen_data()"]
    B --> C{"maxlen == 0 か"}
    C -->|Yes| D["error: バッファ未初期化"]
    C -->|No| E["len = len_data()"]
    E --> F{"limitwarn かつ is_buffer_full() か"}
    F -->|Yes| G["@warn プロファイルバッファ満杯警告"]
    F -->|No| H["警告なし"]
    G --> I["データをコピーして返す"]
    H --> I
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（データベースは使用しない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| バッファ未初期化 | `maxlen_data()` が 0 | error() で例外をスロー |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 無し（ユーザーが `Profile.init()` で再設定後に再度プロファイリングする） |
| リトライ間隔 | -- |
| リトライ対象エラー | -- |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（`fetch()` 呼び出しごとに発生し得る） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし

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

本通知は固定メッセージのみを出力し、機密情報は含まない。

## 備考

- `is_buffer_full()` は C ランタイムの `jl_profile_is_buffer_full` 関数を呼び出す（662行目）。
- `Profile.print` は内部で `fetch` を呼び出すため、`Profile.print()` 実行時にもこの警告が表示される場合がある。
- `Profile.retrieve` も内部で `fetch` を呼び出す。
- デフォルトのバッファサイズ（10,000,000サンプル、delay=0.001秒）では約100秒分のプロファイリングが可能。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Profile.jl | `stdlib/Profile/src/Profile.jl` | プロファイルバッファの概念と C ランタイムのインターフェースを理解する（658-668行目） |

**読解のコツ**: プロファイルバッファは C ランタイム側で管理される。Julia 側からは `len_data()`、`maxlen_data()`、`is_buffer_full()`、`get_data_pointer()` の4つの関数でアクセスする。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Profile.jl | `stdlib/Profile/src/Profile.jl` | `fetch` 関数（686-703行目）が本通知のエントリーポイント |

**主要処理フロー**:
1. **687行目**: `maxlen = maxlen_data()` でバッファの最大サイズを取得
2. **688-690行目**: `maxlen == 0` の場合にバッファ未初期化エラー
3. **691行目**: `len = len_data()` で現在のデータ長を取得
4. **692-696行目**: `limitwarn && is_buffer_full()` で満杯チェックと本通知の発行
5. **697行目**: `Vector{UInt}(undef, len)` でデータコピー用バッファを作成
6. **698行目**: `unsafe_copyto!` でデータをコピー

#### Step 3: バッファ管理関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Profile.jl | `stdlib/Profile/src/Profile.jl` | C ランタイムラッパー関数群（658-668行目） |

**主要処理フロー**:
- **660行目**: `is_running()` -- プロファイラーが動作中か確認
- **662行目**: `is_buffer_full()` -- バッファが満杯か確認（`jl_profile_is_buffer_full`）
- **664行目**: `get_data_pointer()` -- データバッファのポインタを取得
- **666行目**: `len_data()` -- 現在のデータ長を取得
- **668行目**: `maxlen_data()` -- バッファの最大長を取得

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

```
Profile.print() [stdlib/Profile/src/Profile.jl:271]
    |
    +-- fetch(; limitwarn=true) [行686]
            |
            +-- maxlen_data() [行687]
            +-- len_data() [行691]
            +-- is_buffer_full() [行692]
            |       |
            |       +-- true: @warn (No.40 本通知) [行693-695]
            |
            +-- unsafe_copyto!(data, ...) [行698]
```

### データフロー図

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

C ランタイム
プロファイルバッファ -------> fetch()
                               |
                               +-- maxlen_data() チェック
                               +-- len_data() 取得
                               +-- is_buffer_full() チェック
                               |       |
                               |       +-- true --> @warn ログ --> stderr
                               |
                               +-- unsafe_copyto! --> data (Vector{UInt})
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Profile.jl | `stdlib/Profile/src/Profile.jl` | ソース | プロファイルモジュール、`fetch` 関数の定義 |
| logging.jl | `base/logging.jl` | ソース | `@warn` マクロの定義 |
