# 機能設計書 156-常駐メモリサイズ取得

## 概要

本ドキュメントは、libuvライブラリにおけるuv_resident_set_memory()関数によるプロセスの常駐メモリサイズ（RSS）取得機能の設計を記述する。

### 本機能の処理概要

uv_resident_set_memory()関数は、現在のプロセスの常駐セットサイズ（Resident Set Size: 物理メモリ上に実際に存在するページのサイズ）をクロスプラットフォームで取得する機能を提供する。

**業務上の目的・背景**：メモリリーク検出、メモリ使用量の監視、リソース制限の確認など、プロセスのメモリ使用状況を把握することはアプリケーション運用において重要である。各プラットフォームで異なるAPI（task_info、/proc/self/stat、GetProcessMemoryInfo等）を統一的にラップする。

**機能の利用シーン**：メモリ使用量の定期監視、メモリリーク検出のためのRSS推移追跡、リソース使用レポートの生成、プロセスヘルスチェックの一環としてのメモリ確認などに利用される。

**主要な処理内容**：
1. プラットフォーム固有のAPIを使用してRSSを取得
2. 結果をsize_t型で呼び出し元に返す（バイト単位）

**関連システム・外部連携**：
- macOS: task_info(TASK_BASIC_INFO) Mach API
- Linux: /proc/self/stat ファイルの解析
- Windows: GetProcessMemoryInfo()

**権限による制御**：特別な権限は不要。一般ユーザー権限で実行可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 29 | その他ユーティリティ | 主機能 | uv_resident_set_memory()によるRSS取得のAPI定義 |

## 機能種別

データ取得処理（プロセスメモリ使用情報の読み取り）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| rss | size_t* | Yes | RSSを格納するポインタ | 有効なポインタが必要 |

### 入力データソース

OSカーネルからプロセスのメモリ使用情報を取得する。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| *rss | size_t | 常駐セットサイズ（バイト単位） |
| 戻り値 | int | 成功時0、失敗時負のエラーコード |

### 出力先

呼び出し元が提供するsize_t変数に書き込む。

## 処理フロー

### 処理シーケンス

```
1. [macOS] task_info(mach_task_self(), TASK_BASIC_INFO) 呼び出し
   ├─ KERN_SUCCESS以外はassertで異常終了（通常失敗しない）
   └─ *rss = info.resident_size

2. [Linux] /proc/self/statファイルの解析
   ├─ uv__slurp()でファイル内容を読み取り
   ├─ strrchr()で最後の')'を検索（プロセス名の終端）
   ├─ 23番目のフィールド（RSS）まで空白区切りでスキップ
   ├─ strtol()で数値を解析
   └─ *rss = val * getpagesize()（ページ数→バイト変換）

3. [Windows] GetProcessMemoryInfo() 呼び出し
   └─ *rss = pmc.WorkingSetSize
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{プラットフォーム}
    B -->|macOS| C[task_info TASK_BASIC_INFO]
    B -->|Linux| D[/proc/self/stat 読み取り]
    B -->|Windows| E[GetProcessMemoryInfo]
    C --> F[assert KERN_SUCCESS]
    F --> G[*rss = info.resident_size]
    D --> H{読み取り成功?}
    H -->|No| I[return エラー]
    H -->|Yes| J[最後の ) を検索]
    J --> K[23番目のフィールドまでスキップ]
    K --> L[strtol で数値解析]
    L --> M{正常値?}
    M -->|No| N[return エラー]
    M -->|Yes| O[*rss = val * getpagesize]
    E --> P[*rss = WorkingSetSize]
    G --> Q[return 0]
    O --> Q
    P --> Q
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-156-01 | macOS assert | macOSではtask_info()の失敗をassertで検出（通常失敗しない） | macOSプラットフォーム |
| BR-156-02 | ページサイズ変換 | Linuxでは/proc/self/statのRSSはページ数であり、getpagesize()でバイトに変換 | Linuxプラットフォーム |
| BR-156-03 | フィールド位置 | /proc/self/statでRSSは24番目のフィールド（最後の')'から22フィールド先） | Linuxプラットフォーム |

### 計算ロジック

- Linux: `*rss = strtol(rss_field, NULL, 10) * getpagesize()`
- macOS: `*rss = info.resident_size` （バイト単位でそのまま）

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

該当なし（データベース操作は行わない）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV__ERR(errno) | システムエラー | /proc/self/stat読み取り失敗（Linux） | プロセス状態を確認 |
| (assert失敗) | 致命的エラー | task_info()失敗（macOS、通常発生しない） | libuvバグの可能性 |

### リトライ仕様

リトライは不要。

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

該当なし。

## パフォーマンス要件

軽量な処理であり即座に完了する。Linuxでは/proc/self/statの読み取りによるI/Oがあるが、procfsは仮想ファイルシステムであり非常に高速。

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

自プロセスのメモリ情報であり、セキュリティ上の問題は通常ない。

## 備考

- macOS実装ではtask_info(TASK_BASIC_INFO)の失敗をassertで検出している。ソースコメントによれば「task_info(TASK_BASIC_INFO)は本当に失敗できない。KERN_SUCCESS以外はlibuvのバグを示す」とされている。
- Linux実装では/proc/self/statの解析が必要であり、プロセス名に')'が含まれる場合を考慮してstrrchr()で最後の')'を検索している。

---

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

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

### 推奨読解順序

#### Step 1: API宣言を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | uv_resident_set_memory()のAPI宣言（1286行目） |

**読解のコツ**: `UV_EXTERN int uv_resident_set_memory(size_t* rss);` - 結果はバイト単位でsize_t型のポインタに格納される。

#### Step 2: macOS実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | darwin.c | `src/unix/darwin.c` | macOS版uv_resident_set_memory()実装 |

**主要処理フロー**:
- **154行目**: 関数エントリーポイント
- **159-163行目**: task_info(TASK_BASIC_INFO)呼び出し
- **168行目**: `assert(err == KERN_SUCCESS)`
- **169行目**: `*rss = info.resident_size`

#### Step 3: Linux実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | linux.c | `src/unix/linux.c` | Linux版uv_resident_set_memory()実装 |

**主要処理フロー**:
- **1640行目**: 関数エントリーポイント
- **1648行目**: `/proc/self/stat`からの読み取り
- **1653行目**: `strrchr(buf, ')')` で最後の')' を検索
- **1657-1660行目**: 22フィールド（スペース区切り）をスキップ
- **1664行目**: `strtol(s, NULL, 10)` でRSSをパース
- **1668行目**: `*rss = val * getpagesize()` でバイトに変換

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

```
uv_resident_set_memory(rss)
    |
    +-- [macOS] task_info(mach_task_self(), TASK_BASIC_INFO)
    |       +-- assert(err == KERN_SUCCESS)
    |       +-- *rss = info.resident_size
    |
    +-- [Linux] uv__slurp("/proc/self/stat")
    |       +-- strrchr(buf, ')')
    |       +-- 22フィールドスキップ
    |       +-- strtol(s, NULL, 10) * getpagesize()
    |
    +-- [Windows] GetProcessMemoryInfo()
            +-- *rss = pmc.WorkingSetSize
```

### データフロー図

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

rss (size_t*) -------> uv_resident_set_memory()      ---> *rss (バイト)
                       |                                   戻り値: 0 or error
                       +-- task_info / /proc/self/stat /
                           GetProcessMemoryInfo()
                           (プラットフォーム固有API)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | API宣言 |
| darwin.c | `src/unix/darwin.c` | ソース | macOS版uv_resident_set_memory()実装 |
| linux.c | `src/unix/linux.c` | ソース | Linux版uv_resident_set_memory()実装 |
| freebsd.c | `src/unix/freebsd.c` | ソース | FreeBSD版uv_resident_set_memory()実装 |
| netbsd.c | `src/unix/netbsd.c` | ソース | NetBSD版uv_resident_set_memory()実装 |
| openbsd.c | `src/unix/openbsd.c` | ソース | OpenBSD版uv_resident_set_memory()実装 |
| aix.c | `src/unix/aix.c` | ソース | AIX版uv_resident_set_memory()実装 |
| sunos.c | `src/unix/sunos.c` | ソース | Solaris版uv_resident_set_memory()実装 |
| util.c | `src/win/util.c` | ソース | Windows版uv_resident_set_memory()実装 |
