# 非機能要件定義書

## 概要

本ドキュメントは、libuv（バージョン1.52.1-dev）のソースコードを解析し、コードから読み取れる非機能要件を定義したものである。libuvはマルチプラットフォーム対応の非同期I/Oライブラリであり、Node.jsをはじめとする多数のプロジェクトで利用されている。本書はソースコードに実装されている設計判断・制約・設定値を根拠として、性能、可用性、セキュリティ、拡張性、保守性、運用・監視の観点から非機能要件を整理する。

## 性能要件

### レスポンスタイム

| 処理種別 | 目標値 | 備考 |
| --- | --- | --- |
| イベントループ1イテレーション | マイクロ秒～ミリ秒オーダー | `uv_run()`はepoll/kqueue/IOCP等のOS最適I/O多重化機構を使用。`uv__io_poll()`でブロッキング時間はタイマーの最短期限値（`uv__next_timeout()`）で制御される |
| タイマー精度 | ミリ秒単位 | `uv_timer_start()`のtimeout/repeatパラメータはuint64_tのミリ秒単位。タイマーはmin-heapで管理されO(log n)での挿入・削除を実現（`heap-inl.h`） |
| 高精度時刻取得 | ナノ秒精度 | `uv_hrtime()`はプラットフォーム固有の高精度タイマー（CLOCK_MONOTONIC等）を使用し、ナノ秒単位のuint64_tを返却 |
| ファイルシステムポーリング間隔 | 設定可能（最小1ms） | `uv_fs_poll_start()`のintervalパラメータで制御。0指定時は1msに正規化される（`fs-poll.c`） |

### スループット

| 項目 | 目標値 | 備考 |
| --- | --- | --- |
| スレッドプールサイズ | デフォルト4、最大1024 | `UV_THREADPOOL_SIZE`環境変数で設定可能。デフォルトスレッド数は`default_threads[4]`で定義。最大値は`MAX_THREADPOOL_SIZE`（1024）で制限（`threadpool.c`） |
| スレッドスタックサイズ | 8MB | `config.stack_size = 8u << 20`（`threadpool.c`のinit_threads()関数） |
| slow I/Oスレッド制限 | スレッドプール全体の半数（`(nthreads + 1) / 2`） | slow I/Oタスクがスレッドプールを占有しないよう閾値を設定。CPU集約タスクとI/O集約タスクの公平なリソース配分を実現（`threadpool.c`） |
| 同時接続受付 | backlogパラメータで制御 | `uv_listen()`のbacklog引数でTCPの接続キューサイズを指定 |
| UDPデータグラム最大サイズ | 64KB | `UV__UDP_DGRAM_MAXSIZE`は`64 * 1024`として定義（`uv-common.h`） |
| UDPバッチ送信 | recvmmsgサポート | `UV_UDP_RECVMMSG`フラグにより、Linux環境でrecvmmsgシステムコールを使用した高スループットUDP受信が可能 |
| I/Oベクタ最大数 | IOV_MAX（プラットフォーム依存、フォールバック値1024） | `uv__getiovmax()`で取得。sysconf(_SC_IOV_MAX)をキャッシュしてアトミックに保存（`core.c`） |
| SO_REUSEPORTによる負荷分散 | サポート（Linux 3.9+, FreeBSD 12.0+等） | `UV_TCP_REUSEPORT` / `UV_UDP_REUSEPORT`フラグにより複数プロセス/スレッド間での接続分散が可能 |
| TCP_NODELAYサポート | 有効/無効切替可能 | `uv_tcp_nodelay()`でNagleアルゴリズムの無効化が可能。低レイテンシ通信に貢献 |
| 非ブロッキングI/O | 全ソケット・パイプで強制 | `uv__socket()`にてSOCK_NONBLOCK / O_NONBLOCKを設定。全I/Oハンドルが非同期動作を保証 |

### キャッシュ設定

| 項目 | 内容 | 備考 |
| --- | --- | --- |
| IOV_MAXキャッシュ | アトミック変数でキャッシュ | `uv__getiovmax()`は`_Atomic int iovmax_cached`を使用し、sysconf()の呼び出しを初回のみに制限（`core.c`） |
| ループ時刻キャッシュ | `loop->time`フィールド | `uv__update_time()`でイベントループの各イテレーション開始時に更新。ループ内では一貫した時刻を参照可能 |

### タイムアウト設定

| 項目 | 設定値 | 備考 |
| --- | --- | --- |
| イベントループポーリングタイムアウト | 動的計算 | `uv__backend_timeout()`がタイマーヒープの最短期限、pending queue、idle handleの状態に基づいて算出。idle handleが空でpending queueが空の場合のみタイマーまでブロック |
| ファイルシステムポーリング間隔 | ユーザー指定（最小1ms） | `uv_fs_poll_start()`で指定。stat()実行のための遅延を差し引いて次回のタイマーを再スケジュール |
| TCP KeepAliveタイムアウト | ユーザー指定（idle, interval, count） | `uv_tcp_keepalive_ex()`で詳細パラメータ（idle秒、間隔秒、再試行回数）を設定可能。Solarisでは最小10秒制約あり |
| 条件変数タイムアウト | ユーザー指定（ナノ秒単位） | `uv_cond_timedwait()`のtimeoutパラメータで制御 |
| テストタイムアウト倍率 | 環境変数で設定 | `UV_TEST_TIMEOUT_MULTIPLIER`環境変数によりテストタイムアウトを調整可能（デフォルト5秒） |

## 可用性要件

| 項目 | 目標値 | 備考 |
| --- | --- | --- |
| マルチプラットフォーム対応 | Tier 1: Linux(>=3.10/glibc>=2.17), macOS(>=11), Windows(>=10) | Tier 2: FreeBSD(>=12), AIX(>=6), IBM i(>=7.2), z/OS(>=V2R2), Linux(musl>=1.0)。Tier 3: Android(NDK>=r15b), MinGW等 |
| I/Oバックエンド | epoll(Linux), kqueue(macOS/BSD), IOCP(Windows), event ports(Solaris) | プラットフォーム毎に最適なI/O多重化機構を自動選択 |
| io_uringサポート | Linux固有の最適化 | `uv__iou`構造体によりio_uring SQPOLLモードをサポート（`UV_LOOP_USE_IO_URING_SQPOLL`オプション） |
| イベントループ停止・再開 | `uv_stop()` / `uv_run()`で制御 | `loop->stop_flag`によりイベントループの安全な停止と再開が可能 |
| fork()後の再初期化 | `uv_loop_fork()`で対応 | fork後にイベントループを再初期化。スレッドプールは`pthread_atfork`で`reset_once`を登録し自動再初期化 |
| EMFILE対策 | 予備ファイルディスクリプタ | `loop->emfile_fd`で予備FDを確保し、EMFILE（ファイルディスクリプタ枯渇）エラー時にも接続受付を継続可能にする設計（`stream.c`） |
| 作業キャンセル | `uv_cancel()`でリクエストキャンセル | FS, GETADDRINFO, GETNAMEINFO, RANDOM, WORKリクエストのキャンセルをサポート。実行中のリクエストはUV_EBUSYを返却 |
| EINTR再試行 | 全システムコールで自動リトライ | `connect()`, `read()`, `write()`, `close()`, `accept()`, `fcntl()`等のシステムコールがEINTRの場合は自動的にリトライ |
| ECONNREFUSED遅延通知 | プラットフォーム間の動作統一 | Solaris/OpenBSDで即時報告されるECONNREFUSEDを次tickまで遅延させ、プラットフォーム間で一貫した振る舞いを実現（`tcp.c`） |
| 接続エラーの遅延伝播 | `delayed_error`メカニズム | TCPハンドルに`delayed_error`フィールドを持ち、bind時のEADDRINUSE等を接続/書き込み時に報告 |
| ペンディングコールバックの制限実行 | 最大8回/ループ | `uv_run()`内でペンディングコールバック実行をfor文で最大8回に制限し、ループ飢餓を防止（`core.c`） |

## セキュリティ要件

| 項目 | 実装内容 | 備考 |
| --- | --- | --- |
| Close-on-exec (CLOEXEC) | 全ソケット・ファイルで設定 | `uv__socket()`でSOCK_CLOEXECを設定。`uv__open_cloexec()`でO_CLOEXECを設定。子プロセスへのFDリーク防止 |
| ファイルディスクリプタ継承防止 | `uv_disable_stdio_inheritance()` | 最初の16個以降の全FDにCLOEXECフラグを設定し、子プロセスへの不要なFD継承を防止 |
| 暗号学的乱数生成 | プラットフォーム最適なAPIを選択 | `uv_random()`はgetentropy(macOS/OpenBSD)、getrandom(Linux/FreeBSD)、/dev/urandom(フォールバック)、RtlGenRandom(Windows)を使用。バッファサイズは最大0x7FFFFFFF |
| 乱数生成のフォールバック | 多段フォールバック | Linux: getrandom -> /dev/urandom -> sysctl。macOS: getentropy -> /dev/urandom。堅牢な乱数生成を保証 |
| SO_NOSIGPIPE | macOS/BSD系で設定 | パイプ破損時のSIGPIPEシグナルを抑制し、プロセス異常終了を防止（`core.c` uv__socket()内） |
| 入力バリデーション | 全API関数で実施 | NULLポインタチェック、不正な引数値チェック（UV_EINVAL返却）、ハンドルタイプチェック等を網羅的に実施 |
| メモリ安全性 | カスタムアロケータ対応 | `uv_replace_allocator()`でmalloc/realloc/calloc/freeを置換可能。`uv__free()`はerrnoを保存・復元し副作用を防止 |
| シグナルマスク制御 | I/Oポーリング中のシグナルブロック | `uv__io_poll_prepare()`でpthread_sigmask(SIG_BLOCK)を実行し、I/Oポーリング中の割り込みを制御 |
| 脆弱性報告プロセス | GitHub Private Vulnerability Reporting | セキュリティ脆弱性はGitHubのプライベート報告機能を通じて受付（`SECURITY.md`） |
| プロセスユーザー/グループID制御 | `uv_spawn()`オプション | `UV_PROCESS_SETUID` / `UV_PROCESS_SETGID`フラグで子プロセスの実行権限を制御（Unix系のみ） |

## 拡張性要件

| 項目 | 実装内容 | 備考 |
| --- | --- | --- |
| セマンティックバージョニング | SemVer準拠 | v1.x系はABI安定。`UV_VERSION_MAJOR=1`, `UV_VERSION_MINOR=52`, `UV_VERSION_PATCH=1`。メジャーバージョン間でABI互換性保証 |
| ハンドル型の拡張性 | マクロベースの型マップ | `UV_HANDLE_TYPE_MAP`マクロにより新しいハンドル型の追加が体系的に可能 |
| リクエスト型の拡張性 | マクロベースの型マップ | `UV_REQ_TYPE_MAP`マクロにより新しいリクエスト型の追加が体系的に可能 |
| プラットフォーム固有フィールド | PRIVATEマクロパターン | `UV_TCP_PRIVATE_FIELDS`, `UV_LOOP_PRIVATE_FIELDS`等のマクロにより、プラットフォーム固有のデータをハンドル構造体に追加可能 |
| カスタムメモリアロケータ | `uv_replace_allocator()` | malloc/realloc/calloc/freeの4関数を一括置換可能。メモリプールやデバッグアロケータの導入が容易 |
| スレッドプールサイズ動的設定 | 環境変数`UV_THREADPOOL_SIZE` | 起動時に1～1024の範囲でスレッドプールサイズを設定可能 |
| ユーザーデータ領域 | `void* data`フィールド | `uv_loop_t`, `uv_handle_t`, `uv_req_t`すべてにユーザーデータポインタを提供。`uv_handle_set_data()` / `uv_handle_get_data()`でアクセス |
| イベントループ設定 | `uv_loop_configure()` | 可変引数による設定拡張。`UV_LOOP_BLOCK_SIGNAL`, `UV_METRICS_IDLE_TIME`, `UV_LOOP_USE_IO_URING_SQPOLL`等のオプション |
| 共有ライブラリ / 静的ライブラリ | 両形式をサポート | `BUILDING_UV_SHARED` / `USING_UV_SHARED`マクロでdll import/exportを制御。GCCではvisibility("default")を使用 |
| ビルドシステム | CMake / Autotools | CMakeとAutotoolsの両ビルドシステムをサポートし、幅広いビルド環境に対応 |
| 動的関数ロード | ランタイムでの機能検出 | コンパイル時チェックを避け、動的ロード・ランタイム検出を推奨。新しいAPIがサポートされていない場合のフォールバック対応 |

## 保守性要件

| 項目 | 実装内容 | 備考 |
| --- | --- | --- |
| コード構成 | プラットフォーム別ソースファイル分離 | `src/unix/`（Unix系）と`src/win/`（Windows）にプラットフォーム固有コードを分離。共通コードは`src/`直下 |
| 抽象化レイヤ | ハンドル型の継承階層 | `uv_handle_t` -> `uv_stream_t` -> `uv_tcp_t`/`uv_pipe_t`/`uv_tty_t`のような型階層で共通処理を集約 |
| 内部キュー実装 | 侵入型双方向リンクリスト | `uv__queue`構造体による汎用キュー。メモリ確保不要で高効率（`queue.h`） |
| タイマー管理 | min-heap | `heap-inl.h`によるバイナリヒープ実装。O(log n)の挿入・削除・最小値取得 |
| エラーコード体系 | 統一されたエラーコード | `UV_ERRNO_MAP`マクロで60以上のエラーコードを一元管理。`uv_strerror()`, `uv_err_name()`で人間可読な変換 |
| デバッグ支援 | ハンドルダンプ機能 | `uv_print_all_handles()` / `uv_print_active_handles()`でループ内の全ハンドルの状態を出力可能 |
| ハンドルウォーク | `uv_walk()` | ループ内の全ハンドルを列挙しコールバックで処理。リソースリーク検出やクリーンアップに活用 |
| アサーション | デバッグビルドでの整合性チェック | `assert()`によるFD範囲チェック、ハンドル状態チェック、メモリゼロ初期化（`NDEBUG`未定義時にuv_loop_close()でmemset） |
| リソースクリーンアップ | ライブラリシャットダウン | `uv_library_shutdown()`で全リソースの解放。GCC `__attribute__((destructor))`で自動呼び出し（Windows以外） |
| ライセンス | MIT License | 自由な利用・改変・再配布が可能。MITライセンスにより保守・フォークが容易 |

## 運用・監視要件

| 項目 | 実装内容 | 備考 |
| --- | --- | --- |
| イベントループメトリクス | `uv_metrics_t`構造体 | `loop_count`（ループ回数）、`events`（処理イベント数）、`events_waiting`（待機中イベント数）を収集 |
| アイドル時間計測 | `uv_metrics_idle_time()` | `UV_METRICS_IDLE_TIME`オプション有効時、I/Oポーリングのアイドル時間をナノ秒精度で計測。`uv__loop_metrics_t`でmutex保護 |
| メトリクス情報取得 | `uv_metrics_info()` | ループメトリクスのスナップショットを取得可能 |
| リソース使用量取得 | `uv_getrusage()` / `uv_getrusage_thread()` | プロセス/スレッドのCPU時間、最大RSS、ページフォルト、コンテキストスイッチ等のリソース使用量を取得 |
| システム情報取得 | 複数API提供 | `uv_cpu_info()`（CPU情報）、`uv_get_free_memory()`/`uv_get_total_memory()`/`uv_get_constrained_memory()`/`uv_get_available_memory()`（メモリ情報）、`uv_loadavg()`（負荷平均）、`uv_os_uname()`（OS情報） |
| ファイルシステム監視 | `uv_fs_event_t` / `uv_fs_poll_t` | inotify(Linux)/kqueue(macOS/BSD)/ReadDirectoryChangesW(Windows)によるイベント駆動監視と、stat()ベースのポーリング監視の両方をサポート |
| プロセス管理 | `uv_spawn()` / `uv_process_kill()` | 子プロセスの起動・終了監視・シグナル送信。`UV_PROCESS_DETACHED`でデーモン化対応 |
| シグナルハンドリング | `uv_signal_t` | `uv_signal_start()`/`uv_signal_start_oneshot()`でシグナルの捕捉。イベントループ内で安全にシグナル処理 |
| 利用可能並列度 | `uv_available_parallelism()` | CPU affinity、cgroup制約を考慮した実効的な並列処理可能数を返却。コンテナ環境でのリソース制限に対応 |
| rlimit制約の検出 | `uv__get_rlimit_max_memory()` | RLIMIT_ASとRLIMIT_DATAからプロセスのメモリ制限を検出 |
| スレッド名設定 | `uv_thread_setname()` / `uv_thread_getname()` | スレッドに名前を付与可能。デバッグ・監視ツールでの識別に利用。スレッドプールワーカーは"libuv-worker"と命名 |
| プロセスタイトル設定 | `uv_set_process_title()` | プロセス名を動的に変更可能。ps/top等の監視ツールでの識別に活用 |
| ネットワークインターフェース情報 | `uv_interface_addresses()` | ネットワークインターフェースのアドレス、MACアドレス、内部フラグを取得可能 |

## 備考

- 本ドキュメントはlibuvバージョン1.52.1-dev（`include/uv/version.h`）のソースコードを解析して作成されたものである
- libuvはCライブラリであり、レートリミットやHTTPレベルのキャッシュ等のアプリケーションレベルの非機能要件は含まない。これらはlibuvを利用するアプリケーション側で実装される
- タイムアウト値や接続数等の具体的な数値制限は、OS側のカーネルパラメータ（somaxconn、rlimit等）に依存する部分が多い
- libuv自体にはログ出力機構は組み込まれていない。デバッグ目的の`uv_print_all_handles()`やメトリクスAPIを通じた間接的な監視が主な手段となる
- ThreadSanitizerやValgrindとの互換性に配慮した実装（`__SANITIZE_THREAD__`マクロによる分岐等）がなされている
