# 通知設計書 38-プロファイルバッファ制限警告

## 概要

本ドキュメントは、32ビットシステムにおいてプロファイルバッファのサイズが512MBに制限される場合に出力される警告通知の設計を記述する。

### 本通知の処理概要

本通知は、`Profile.init` 関数でプロファイルバッファサイズを設定する際に、32ビットシステムのメモリ制約により要求されたサイズが512MB（2^29バイト）に切り詰められた場合にワーニングレベルのログを出力する処理である。

**業務上の目的・背景**：Julia のプロファイラーは、サンプリングされたスタックトレース情報をメモリ内のバッファに蓄積する。32ビットシステムではアドレス空間が限られている（最大4GB、実効的にはそれ以下）ため、プロファイルバッファが大きすぎるとメモリ不足になる。本通知は、要求されたバッファサイズが自動的に制限された場合にユーザーに知らせるために設けられている。

**通知の送信タイミング**：`init(n::Integer, delay::Real)` 関数内で `buffer_size_bytes > 2^29` かつ `Sys.WORD_SIZE == 32` の条件が成立した時点で送信される。具体的には `stdlib/Profile/src/Profile.jl` の151行目で発火する。

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

**通知内容の概要**：`"Requested profile buffer limited to 512MB (n = {制限後のサンプル数}) given that this system is 32-bit"` という警告メッセージが出力される。

**期待されるアクション**：開発者はプロファイルバッファサイズが自動的に制限されたことを認識する。必要に応じて、より短い時間でプロファイリングを実行するか、64ビットシステムに移行する。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

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

## 通知テンプレート

### メール通知の場合

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

### 本文テンプレート

```
Requested profile buffer limited to 512MB (n = {buffer_samples}) given that this system is 32-bit
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| buffer_samples | 制限後のサンプル数 | `floor(Int, 2^29 / sample_size_bytes)` | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| プロファイル初期化 | `Profile.init(n, delay)` の呼び出し | `buffer_size_bytes > 2^29` かつ `Sys.WORD_SIZE == 32` かつ `limitwarn == true` | `init` 関数内の条件分岐で検出 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 64ビットシステム | `Sys.WORD_SIZE != 32` の場合、512MB 制限は適用されない |
| バッファサイズが制限内 | `buffer_size_bytes <= 2^29` の場合、制限は不要 |
| `limitwarn = false` | 明示的に警告が無効化された場合（例：`default_init` からの呼び出し時） |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A["Profile.init(n, delay) 呼び出し"] --> B["sample_size_bytes = sizeof(Ptr)"]
    B --> C["buffer_size_bytes = n * sample_size_bytes"]
    C --> D{"buffer_size_bytes > 2^29 かつ 32ビット?"}
    D -->|No| E["通常のバッファ設定"]
    D -->|Yes| F["buffer_samples = floor(Int, 2^29 / sample_size_bytes)"]
    F --> G{"limitwarn == true か"}
    G -->|Yes| H["@warn プロファイルバッファ制限警告"]
    G -->|No| I["警告なしで制限適用"]
    H --> J["ccall(:jl_profile_init, ...)"]
    I --> J
    E --> J
```

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

### 参照テーブル一覧

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

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| バッファ確保失敗 | `jl_profile_init` が -1 を返す | error() で例外をスロー |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 無し |
| リトライ間隔 | -- |
| リトライ対象エラー | -- |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし

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

本通知はシステム情報（32ビットであること、バッファサンプル数）を含むが、機密情報は含まない。

## 備考

- `default_init` 関数（159-174行目）からの呼び出しでは `limitwarn = false` が指定されるため、デフォルト初期化時にはこの警告は出力されない。
- 32ビットシステムでのデフォルトのバッファサイズは `default_init` の値（Windows 32ビットで1,000,000サンプル、その他で10,000,000サンプル）であり、これらはすでに512MB以内に収まるように設計されている。
- `sample_size_bytes` は `sizeof(Ptr)` であり、32ビットシステムでは4バイト。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Profile.jl | `stdlib/Profile/src/Profile.jl` | `nmeta` 定数（44行目）とプロファイルバッファの概念を理解する |

**読解のコツ**: プロファイルバッファは命令ポインタ（IP）の配列であり、各サンプルは `sizeof(Ptr)` バイトを消費する。32ビットでは4バイト/サンプル、64ビットでは8バイト/サンプルである。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Profile.jl | `stdlib/Profile/src/Profile.jl` | `init(n::Integer, delay::Real)` 関数（144-157行目）が本通知のエントリーポイント |

**主要処理フロー**:
1. **145行目**: `sample_size_bytes = sizeof(Ptr)` でサンプルサイズを計算
2. **147行目**: `buffer_size_bytes = buffer_samples * sample_size_bytes` でバッファサイズを計算
3. **148行目**: `buffer_size_bytes > 2^29 && Sys.WORD_SIZE == 32` で制限判定
4. **149行目**: `buffer_samples = floor(Int, 2^29 / sample_size_bytes)` でサンプル数を制限
5. **151行目**: `limitwarn && @warn` で本通知を発行
6. **153行目**: `ccall(:jl_profile_init, ...)` でバッファを初期化

#### Step 3: デフォルト初期化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Profile.jl | `stdlib/Profile/src/Profile.jl` | `default_init` 関数（159-174行目）がデフォルトのバッファサイズを設定 |

**主要処理フロー**:
- **163-166行目**: Windows 32ビットでは n=1,000,000, delay=0.01
- **169-170行目**: その他では n=10,000,000, delay=0.001
- **173行目**: `init(n, delay, limitwarn = false)` で警告なしで初期化

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

```
Profile.init(; n, delay) [stdlib/Profile/src/Profile.jl:128]
    |
    +-- init(n, delay; limitwarn) [行144]
            |
            +-- バッファサイズ計算 [行145-147]
            +-- 32ビット制限チェック [行148]
            |       |
            |       +-- @warn (No.38 本通知) [行151]
            |
            +-- ccall(:jl_profile_init, ...) [行153]
```

### データフロー図

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

n (サンプル数)
delay (秒) -------------> init(n, delay)
                            |
                            +-- バッファサイズ計算
                            |       |
                            |       +-- 32ビット & > 512MB
                            |               |
                            |               +--> 制限適用 & @warn ログ --> stderr
                            |
                            +-- ccall(:jl_profile_init) --> C ランタイムバッファ確保
```

### 関連ファイル一覧

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