# 機能設計書 20-worker_threads

## 概要

本ドキュメントは、Node.jsのworker_threadsモジュール（マルチスレッド実行機能）の機能設計を記述したものである。

### 本機能の処理概要

worker_threads機能は、Node.jsでマルチスレッド実行を可能にするAPIを提供する。メインスレッドからワーカースレッドを生成し、並列処理を実現する。スレッド間ではMessagePortを通じたメッセージパッシング、SharedArrayBufferによる共有メモリ、Atomicsによる同期が可能である。

**業務上の目的・背景**：CPU集約的な処理をメインスレッドから分離し、イベントループのブロックを回避する。プロセス生成よりも軽量で、メモリ効率の良い並列処理を実現できる。

**機能の利用シーン**：
- CPU集約的な計算処理（画像処理、暗号化等）
- 大量データの並列処理
- バックグラウンドタスクの実行
- イベントループのブロック回避
- リアルタイム処理の負荷分散

**主要な処理内容**：
1. ワーカースレッド生成（new Worker()）
2. スレッド間メッセージ通信（postMessage、MessagePort、MessageChannel）
3. 共有メモリ（SharedArrayBuffer、Atomics）
4. 環境データ共有（setEnvironmentData、getEnvironmentData）
5. リソース制限（resourceLimits）
6. プロファイリング（CPUプロファイル、ヒーププロファイル）

**関連システム・外部連携**：
- cluster: マルチプロセス（代替手段）
- child_process: 子プロセス生成（代替手段）

**権限による制御**：InternalWorkerはPermission Modelをバイパスする。

## 関連画面

本機能はCLI/APIレベルの機能であり、直接関連する画面はない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | - |

## 機能種別

並列処理 / スレッド管理 / メッセージ通信

## 入力仕様

### 入力パラメータ

#### new Worker(filename[, options])

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| filename | string/URL | Yes | 実行スクリプト | 絶対パスまたは./相対パス |
| options.workerData | any | No | ワーカーへ渡すデータ | クローン可能 |
| options.eval | boolean | No | filenameを評価コードとして扱う | デフォルトfalse |
| options.stdin | boolean | No | stdinストリーム有効化 | デフォルトfalse |
| options.stdout | boolean | No | stdoutを親にパイプしない | デフォルトfalse |
| options.stderr | boolean | No | stderrを親にパイプしない | デフォルトfalse |
| options.execArgv | string[] | No | Node.js引数 | 配列 |
| options.argv | string[] | No | process.argv | 配列 |
| options.env | Object/SHARE_ENV | No | 環境変数 | SHARE_ENVで共有 |
| options.name | string | No | スレッド名 | 文字列 |
| options.resourceLimits | Object | No | リソース制限 | 各種制限値 |
| options.trackUnmanagedFds | boolean | No | 管理外FD追跡 | デフォルトtrue |
| options.transferList | Array | No | 転送オブジェクト | Transferable配列 |

#### resourceLimitsオプション

| パラメータ名 | 型 | 説明 |
|-------------|-----|------|
| maxOldGenerationSizeMb | number | V8 Old世代最大サイズ（最小2MB） |
| maxYoungGenerationSizeMb | number | V8 Young世代最大サイズ |
| codeRangeSizeMb | number | コード範囲サイズ |
| stackSizeMb | number | スタックサイズ |

### 入力データソース

- スクリプトファイル
- workerData
- 環境変数
- MessagePortからのメッセージ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| isMainThread | boolean | メインスレッド判定 |
| isInternalThread | boolean | 内部スレッド判定 |
| threadId | number | スレッドID |
| threadName | string | スレッド名 |
| parentPort | MessagePort | 親スレッドへのポート（ワーカー内） |
| workerData | any | 親から渡されたデータ（ワーカー内） |
| resourceLimits | Object | リソース制限値 |

### Workerオブジェクト

| 項目名 | 型 | 説明 |
|--------|-----|------|
| worker.threadId | number | ワーカースレッドID |
| worker.threadName | string | ワーカースレッド名 |
| worker.stdin | Writable | 標準入力ストリーム |
| worker.stdout | Readable | 標準出力ストリーム |
| worker.stderr | Readable | 標準エラーストリーム |
| worker.resourceLimits | Object | リソース制限値 |
| worker.performance | Object | パフォーマンス情報 |

### 出力先

- アプリケーションコード（イベント、プロパティ）
- MessagePort

## 処理フロー

### 処理シーケンス

```
1. Worker生成
   └─ options検証
   └─ WorkerImpl（ネイティブ）生成
   └─ MessagePort設定
2. スクリプトロード
   └─ LOAD_SCRIPTメッセージ送信
   └─ ワーカースレッド起動
3. ワーカー初期化
   └─ workerData設定
   └─ parentPort設定
   └─ UP_AND_RUNNINGメッセージ送信
4. メッセージ通信
   └─ postMessage()
   └─ MessagePort経由
5. 終了処理
   └─ terminate()またはexit
   └─ ポートクローズ
   └─ exitイベント発火
```

### フローチャート

```mermaid
flowchart TD
    A[new Worker] --> B[options検証]
    B --> C[WorkerImpl生成]
    C --> D[MessagePort設定]
    D --> E[LOAD_SCRIPT送信]
    E --> F[startThread]
    F --> G[ワーカー起動]
    G --> H[workerData/parentPort設定]
    H --> I[onlineイベント]
    I --> J{メッセージ?}
    J -->|Yes| K[postMessage処理]
    J -->|terminate| L[stopThread]
    K --> J
    L --> M[exitイベント]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | パス制限 | filenameは絶対パスまたは./..相対パス | eval=false時 |
| BR-002 | SHARE_ENV | 環境変数をメインスレッドと共有 | options.env=SHARE_ENV |
| BR-003 | transferList | ArrayBuffer等は転送（移動）される | postMessage時 |
| BR-004 | resourceLimits | V8ヒープサイズ制限（最小2MB） | Worker生成時 |
| BR-005 | cwd同期 | process.chdir()はワーカーにカウンターで同期 | メインスレッドでchdir時 |

### 計算ロジック

#### リソース制限パース
```javascript
function parseResourceLimits(obj) {
  const ret = new Float64Array(kTotalResourceLimitCount);
  TypedArrayPrototypeFill(ret, -1);
  if (typeof obj !== 'object' || obj === null) return ret;
  if (typeof obj.maxOldGenerationSizeMb === 'number')
    ret[kMaxOldGenerationSizeMb] = MathMax(obj.maxOldGenerationSizeMb, 2);
  // ...
  return ret;
}
```

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

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | - |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR_WORKER_PATH | Error | 相対パスが./..で始まらない | 絶対パスまたは./相対パス |
| ERR_WORKER_NOT_RUNNING | Error | 停止中のワーカーへ操作 | ワーカー状態を確認 |
| ERR_WORKER_UNSERIALIZABLE_ERROR | Error | エラーがシリアライズ不可 | シリアライズ可能なエラー |
| ERR_WORKER_INVALID_EXEC_ARGV | Error | 不正なexecArgv | 有効な引数を使用 |
| ERR_INVALID_ARG_TYPE | TypeError | 引数型不正 | 正しい型を使用 |
| ERR_INVALID_ARG_VALUE | TypeError | 引数値不正 | 正しい値を使用 |
| ERR_OPERATION_FAILED | Error | cpuUsage()がSunOSで使用不可 | 別プラットフォーム使用 |

### リトライ仕様

本機能にリトライ仕様はない。

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

本機能にトランザクション仕様はない。

## パフォーマンス要件

- スレッド生成はプロセス生成より軽量
- MessagePortはIPC高速化
- SharedArrayBufferでコピーなし共有
- resourceLimitsでメモリ使用量を制限可能

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

- InternalWorkerはPermission Modelをバイパス
- SharedArrayBufferはSpectreリスクあり
- ワーカーは親と同じ権限で実行

## 備考

- workerDataはStructured Cloneでコピー
- transferListでArrayBuffer等を移動（ゼロコピー）
- BroadcastChannelで複数スレッドへ同報
- Atomicsでスレッド間同期
- locksでWeb Locks API互換のロック機構
- SymbolAsyncDisposeでusing構文対応
- diagnostics_channel 'worker_threads'で監視可能

---

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

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

### 推奨読解順序

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

エクスポートされるAPIを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | worker_threads.js | `lib/worker_threads.js` | module.exports（35-57行目） |

**読解のコツ**: 複数の内部モジュールからAPIを集約してエクスポートしている。

#### Step 2: Workerクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | internal/worker.js | `lib/internal/worker.js` | Workerクラス（198-597行目） |

**主要処理フロー**:
- **199-364行目**: constructor - Worker初期化
- **366-383行目**: kOnExit - 終了処理
- **395-423行目**: kOnMessage - メッセージ受信処理
- **443-447行目**: postMessage - メッセージ送信
- **449-464行目**: terminate - ワーカー終了
- **514-527行目**: getHeapSnapshot - ヒープスナップショット

#### Step 3: メッセージ通信を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | internal/worker/io.js | `lib/internal/worker/io.js` | MessagePort/MessageChannel |

**主要処理フロー**:
- MessagePortクラス
- MessageChannelクラス
- receiveMessageOnPort関数

#### Step 4: 環境データを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | internal/worker.js | `lib/internal/worker.js` | setEnvironmentData/getEnvironmentData（120-129行目） |

**主要処理フロー**:
- **109行目**: environmentData（SafeMap）
- **120-125行目**: setEnvironmentData()
- **127-129行目**: getEnvironmentData()

#### Step 5: プロファイリングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | internal/worker.js | `lib/internal/worker.js` | CPUProfileHandle/HeapProfileHandle（138-196行目） |

**主要処理フロー**:
- **138-167行目**: CPUProfileHandle
- **169-196行目**: HeapProfileHandle
- **572-583行目**: startCpuProfile()
- **585-596行目**: startHeapProfile()

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

```
worker_threads (lib/worker_threads.js)
    |
    +-- isMainThread, isInternalThread, threadId, threadName
    |
    +-- Worker (lib/internal/worker.js)
    |       |
    |       +-- constructor(filename, options)
    |       |       +-- WorkerImpl [native]
    |       |       +-- MessagePort設定
    |       |       +-- LOAD_SCRIPTメッセージ
    |       |       +-- startThread()
    |       |
    |       +-- postMessage(value, transferList)
    |       |       +-- kPublicPort.postMessage()
    |       |
    |       +-- terminate()
    |       |       +-- stopThread() [native]
    |       |
    |       +-- getHeapSnapshot(options)
    |       +-- getHeapStatistics()
    |       +-- cpuUsage(prev)
    |       +-- startCpuProfile()
    |       +-- startHeapProfile()
    |       |
    |       +-- ref() / unref()
    |       +-- [SymbolAsyncDispose]()
    |
    +-- MessageChannel (lib/internal/worker/io.js)
    |       +-- port1, port2 (MessagePort)
    |
    +-- MessagePort (lib/internal/worker/io.js)
    |       +-- postMessage(value, transferList)
    |       +-- on('message') / on('messageerror')
    |       +-- start() / close()
    |       +-- ref() / unref()
    |
    +-- BroadcastChannel (lib/internal/worker/io.js)
    |       +-- postMessage(value)
    |       +-- on('message')
    |       +-- close()
    |
    +-- receiveMessageOnPort(port)
    +-- markAsUncloneable(obj)
    +-- markAsUntransferable(obj)
    +-- moveMessagePortToContext(port, ctx)
    |
    +-- setEnvironmentData(key, value)
    +-- getEnvironmentData(key)
    |
    +-- postMessageToThread(threadId, value, transferList)
    |
    +-- resourceLimits
    +-- SHARE_ENV
    +-- locks

internal/worker.js 内部
    |
    +-- environmentData (SafeMap)
    +-- cwdCounter (SharedArrayBuffer)
    +-- CPUProfileHandle
    +-- HeapProfileHandle
    +-- InternalWorker (extends Worker)
```

### データフロー図

```
[メインスレッド]                          [ワーカースレッド]

new Worker(filename, options)
      |
      v
WorkerImpl生成 -----------------------> スレッド生成
      |                                       |
      v                                       v
LOAD_SCRIPT ---------------------------> スクリプトロード
      |                                       |
      v                                       |
      |                               workerData設定
      |                               parentPort設定
      |                                       |
      +-- onlineイベント <--------------- UP_AND_RUNNING
      |                                       |
      v                                       v
postMessage() -----------------------> parentPort.on('message')
      |                                       |
      |                                       v
on('message') <----------------------- parentPort.postMessage()
      |                                       |
      |                               SharedArrayBuffer
      +-- 共有メモリ ----------------+       |
      |                               Atomics |
      v                                       v
terminate() --------------------------> 終了処理
      |                                       |
      v                                       |
exitイベント <------------------------ process.exit()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| worker_threads.js | `lib/worker_threads.js` | ソース | 公開APIエントリポイント |
| internal/worker.js | `lib/internal/worker.js` | ソース | Workerクラス実装 |
| internal/worker/io.js | `lib/internal/worker/io.js` | ソース | MessagePort/MessageChannel |
| internal/worker/messaging.js | `lib/internal/worker/messaging.js` | ソース | postMessageToThread |
| internal/buffer.js | `lib/internal/buffer.js` | ソース | markAsUntransferable |
| internal/locks.js | `lib/internal/locks.js` | ソース | Web Locks API |
| internal/error_serdes.js | `lib/internal/error_serdes.js` | ソース | エラーシリアライズ |
| src/node_worker.cc | `src/node_worker.cc` | C++ソース | ネイティブWorker実装 |
