# 機能設計書 5-メモリ管理

## 概要

本ドキュメントは、Apache Flinkのメモリ管理機能について詳細に記載する。メモリ管理はカスタムメモリ管理によるin-memory/out-of-coreデータ処理を実現し、効率的なメモリ使用とガベージコレクション負荷の軽減を提供する。

### 本機能の処理概要

Flinkのメモリ管理機能は、MemorySegmentを中心としたカスタムメモリ管理を提供する。MemorySegmentはFlinkが管理するメモリの一片を表し、オンヒープ、オフヒープダイレクト、オフヒープアンセーフの3種類のメモリをトランスペアレントに扱う。JavaのByteBufferと類似の機能を提供しつつ、より効率的なバイナリ操作とメモリ管理を実現する。

**業務上の目的・背景**：大規模データ処理において、JVMのガベージコレクション（GC）は重大なパフォーマンス問題を引き起こす可能性がある。特にフルGCは長時間の停止を招き、レイテンシに敏感なストリーム処理では致命的となる。Flinkのメモリ管理は、オフヒープメモリの活用とカスタムシリアライゼーションにより、GC負荷を最小限に抑え、予測可能なパフォーマンスを実現する。また、メモリが不足した場合はディスクにスピルすることで、利用可能なメモリを超えるデータセットの処理も可能にする。

**機能の利用シーン**：
- バッファ管理（ネットワーク転送、ソート、ハッシュテーブル）
- ステート管理のバックエンド
- シリアライゼーション/デシリアライゼーション
- スピル処理（メモリ不足時のディスク書き出し）

**主要な処理内容**：
1. MemorySegment：メモリの基本単位、バイトアクセス操作
2. MemorySegmentFactory：MemorySegmentの生成
3. DataInputView/DataOutputView：シリアライゼーションのためのインターフェース
4. ManagedMemoryUseCase：マネージドメモリの用途定義

**関連システム・外部連携**：メモリ管理はTaskManager、ステートバックエンド、ネットワークスタック、ソートアルゴリズム等と密接に連携する。

**権限による制御**：メモリ管理自体には権限制御は存在しない。

## 関連画面

本機能はバックエンドのシステム機能であり、直接関連する画面は存在しない。ただし、TaskManagerメトリクス画面でメモリ使用状況を確認可能。

## 機能種別

システム基盤 / メモリ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| buffer | byte[] / ByteBuffer | Yes | メモリ領域 | size >= 8 |
| owner | Object | No | メモリの所有者 | - |

### 入力データソース

- TaskManagerのメモリプール
- ネットワークバッファプール

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| MemorySegment | MemorySegment | メモリセグメントインスタンス |

### 出力先

- オペレーターのバッファ
- シャッフル/ソート処理
- ステートバックエンド

## 処理フロー

### 処理シーケンス

```
1. MemorySegment生成
   └─ MemorySegmentFactory.wrap()またはallocate系メソッド
2. データ書き込み
   └─ put系メソッドでバイナリデータを書き込み
3. データ読み取り
   └─ get系メソッドでバイナリデータを読み取り
4. メモリ解放
   └─ free()メソッドでメモリを解放
```

### フローチャート

```mermaid
flowchart TD
    A[メモリ要求] --> B{メモリタイプ}
    B -->|OnHeap| C[byte配列確保]
    B -->|OffHeap Direct| D[DirectByteBuffer確保]
    B -->|OffHeap Unsafe| E[Unsafeメモリ確保]
    C --> F[MemorySegment生成]
    D --> F
    E --> F
    F --> G[データ操作]
    G --> H[メモリ解放]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 最小サイズ | MemorySegmentは最小8バイト必要 | 常時 |
| BR-002 | ラップ制限 | UnsafeメモリはByteBufferラップ不可 | Unsafeメモリ使用時 |
| BR-003 | スレッドセーフ | 絶対位置指定メソッドはスレッドセーフ | 並行アクセス時 |

### 計算ロジック

**アドレス計算**：
- オンヒープ: BYTE_ARRAY_BASE_OFFSET + offset
- オフヒープ: 絶対アドレス + offset

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

本機能は直接データベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | IndexOutOfBoundsException | 範囲外アクセス | オフセットとサイズを確認 |
| - | BufferOverflowException | バッファオーバーフロー | 十分なサイズを確保 |
| - | IllegalArgumentException | ByteBufferが非ダイレクト | ダイレクトバッファを使用 |

### リトライ仕様

メモリ管理はリアルタイム処理のため、リトライ仕様は存在しない。

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

メモリ管理にはトランザクション機能はない。

## パフォーマンス要件

- put/get操作はネイティブ命令レベルの高速性
- リトルエンディアン/ビッグエンディアンの明示的アクセスサポート

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

- オフヒープメモリはGCの管理外のため、明示的な解放が必要
- メモリリークに注意

## 備考

MemorySegmentは@Internalアノテーションが付与されており、内部APIである。

---

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

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

### 推奨読解順序

#### Step 1: 基本クラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | MemorySegment.java | `flink-core/src/main/java/org/apache/flink/core/memory/MemorySegment.java` | メモリ管理の中核クラス |

**読解のコツ**:
- **42-68行目**: JavaDocでMemorySegmentの役割と設計意図を理解
- **70行目**: @Internalアノテーションとfinalクラス定義
- **104行目**: heapMemory（オンヒープ用byte配列）
- **110行目**: offHeapBuffer（オフヒープ用ByteBuffer）
- **116行目**: address（メモリアドレス）
- **122行目**: addressLimit（終端アドレス）
- **125行目**: size（サイズ）
- **152-162行目**: オンヒープコンストラクタ
- **176-178行目**: オフヒープコンストラクタ

#### Step 2: ファクトリメソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MemorySegmentFactory.java | `flink-core/src/main/java/org/apache/flink/core/memory/MemorySegmentFactory.java` | MemorySegment生成のファクトリ |

#### Step 3: データビューを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | DataInputView.java | `flink-core/src/main/java/org/apache/flink/core/memory/DataInputView.java` | 読み取りビュー |
| 3-2 | DataOutputView.java | `flink-core/src/main/java/org/apache/flink/core/memory/DataOutputView.java` | 書き込みビュー |

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

```
MemorySegmentFactory
    │
    ├─ wrap(byte[]) → オンヒープMemorySegment
    ├─ wrap(ByteBuffer) → オフヒープMemorySegment
    └─ allocateUnpooledSegment() → 新規MemorySegment
           │
           └─ MemorySegment
                  │
                  ├─ get/put系メソッド → バイナリアクセス
                  ├─ wrap(ByteBuffer) → NIOバッファ連携
                  └─ free() → メモリ解放
```

### データフロー図

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

TaskManager ───▶ MemorySegmentFactory ───▶ MemorySegment
メモリプール              │                        │
     │                   │                        ▼
     └─ 設定             └─ メモリ確保      バッファ操作
                                                  │
                                                  ▼
                                            オペレーター処理
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MemorySegment.java | `flink-core/src/main/java/org/apache/flink/core/memory/MemorySegment.java` | ソース | メモリセグメント |
| MemorySegmentFactory.java | `flink-core/src/main/java/org/apache/flink/core/memory/MemorySegmentFactory.java` | ソース | ファクトリ |
| DataInputView.java | `flink-core/src/main/java/org/apache/flink/core/memory/DataInputView.java` | ソース | 入力ビュー |
| DataOutputView.java | `flink-core/src/main/java/org/apache/flink/core/memory/DataOutputView.java` | ソース | 出力ビュー |
| DataInputDeserializer.java | `flink-core/src/main/java/org/apache/flink/core/memory/DataInputDeserializer.java` | ソース | デシリアライザ |
| DataOutputSerializer.java | `flink-core/src/main/java/org/apache/flink/core/memory/DataOutputSerializer.java` | ソース | シリアライザ |
| ManagedMemoryUseCase.java | `flink-core/src/main/java/org/apache/flink/core/memory/ManagedMemoryUseCase.java` | ソース | 用途定義 |
| MemoryUtils.java | `flink-core/src/main/java/org/apache/flink/core/memory/MemoryUtils.java` | ソース | ユーティリティ |
