nproxy はランタイム I/O プロキシである。 制御コードは解釈せず透過し、シグナルは中継する。 プロトコルや意味付けは nproxy の外側で行う。
node -r ./node/nproxy.js app.js # Node preload mode (CJS)
NODE_OPTIONS="-r nproxy.js" app # Node preload mode (ESM, 推奨)
cargo run -- command [args...] # Rust CLI mode
この 3 点は言語・実装を問わず nproxy の根幹を定義する。 これらが動かなければ実装失敗。 コードレビュー時のチェックリスト。
chunk (Buffer / bytes) は passthrough する瞬間以外メモリに留めない。 観測は size / ts / kind のメタ情報のみ。
| 違反時に起きる現象 |
|---|
| OOM(即時 / 緩慢) |
- Rust:
tokio::io::copy/copy_bufで OS バッファに任せる - Node:
pipe()のみ。dataイベントで自前バッファに保持しない - Go:
io.Copy/io.CopyBufferでゼロアロケーション
自前でバッファを積まない。OS poll の「読まない → カーネル pipe buffer に詰まる → 上流 blocking」機構に乗る。
| 違反時に起きる現象 |
|---|
| flowing-mode 固定で機構破壊 → OOM か stall |
- 読むのを止める = 子の write をブロック が唯一の正しい backpressure
Poll::Pending(Rust) /ReadStop(Node libuv) / 単に read しない (Go)- バッファリングは OS の役割。nproxy はバッファしない
本流 (passthrough) は絶対に止めない/拒否しない。 縮退するのは観測解像度・ring buffer・text mode などの副作用のみ。
| 違反時に起きる現象 |
|---|
| 「拒否しない/止めない」要件違反。プロキシの存在意義が消える |
| state | byte 層 | text 層 |
|---|---|---|
| NORMAL | 詳細観測 + ring 1024 件 | text-on-by-config |
| PRESSURE | サマリ観測 + ring 128 件 + text-AUTO-OFF | 重い変換は停止 |
| CRITICAL | 観測停止 + ring 0 件 + text-完全OFF + ReadGate closed | backpressure で子を抑制 |
どの状態でも passthrough の本流は動き続ける。 CRITICAL でも ReadGate で読み出しを止めるのは backpressure の本流動作であって遮断ではない。 子が write をブロックされても nproxy は「読み出せる状態を待っている」だけ。
# NODE_OPTIONS 経由で preload。--max-old-space-size と --expose-gc を両方指定すると
# openclaude 等の spawnSync 再起動を防止できる。
SIZE_MB=$(( $(awk '/MemTotal/{printf "%.0f", $2/1024}' /proc/meminfo) * 3 / 4 ))
NODE_OPTIONS="--expose-gc --max-old-space-size=$SIZE_MB -r $HOME/workfolder/Nproxy/node/nproxy.js" \
my-esm-app.mjsnode -r ./node/nproxy.js my-app.jsprocess.stdout.writeフック + メモリ監視による自動 mode 縮退- 256KB チャンク分割 — 256KB 超の write は自動分割
- 5段階メモリガード: monitoring → attention(256MB) → pressure(512MB) → critical(1024MB) → emergency(1280MB)
- pressure: 自動 strip-ansi 切替、チャンクサイズ 64KB に縮小
- critical: チャンクサイズ 4KB、緊急モード
- emergency: coalesce バイパス、即時書き出し
- V8 NearHeapLimitCallback C++ addon (
node/nheap_limit/) — V8 OOM 直前に発動、emergency 状態へ強制遷移 - coalescing でフレームレート低下防止(Ink 等の対話型CLI向け)
- attention (黄) / pressure (赤) / critical (青) / emergency (マゼンタ) の色付き stderr フィードバック
- 起動時
◈ nproxy memory guard activeバナーを最初の出力直下に注入 - cursor show/hide (
?25h/?25l) は transform/strip-ansi でも保持 - Windows: 未定義シグナルを try/catch でガード
- alias の注意:
~ではなく$HOMEを使うこと(シングルクォート内の~は展開されない場合がある) - ヒープ再起動防止: openclaude 等の一部アプリは
--expose-gc+--max-old-space-sizeが不足しているとspawnSyncで自身を再起動する。NODE_OPTIONSに両方を含めることで単一プロセスで動作する。 - インストーラ:
install.shを実行すると搭載RAMに応じたヒープサイズを対話的に設定できる。
cargo run --release -- command [args...]
cargo run --release -- --text=strip-ansi -- command [args...]tokio::process::Command+AsyncRead/AsyncWriterelayReadGateによる poll 停止ベースの backpressure/proc/<child_pid>/statusRSS 監視 → watch channel → relay へ通知- TextPipeline: passthrough / strip-ansi / transform + 自動縮退
| 設計思想 | Node 実装 | Rust 実装 | 共通の根 |
|---|---|---|---|
| chunk 非保持 | pipe() のみ |
tokio::io::copy / copy_buf |
OS バッファに任せる |
| backpressure | libuv ReadStop/ReadStart | Tokio AsyncRead poll → Poll::Pending |
OS poll 停止/再開 |
| policy 縮退 | JS state + setInterval | MemoryPolicy + watch channel |
状態は副作用のみ |
| chunk = 最小単位 | Buffer (V8 ArrayBuffer) | Bytes/BytesMut |
OS ページ単位 |
| ランタイム I/O | libuv | epoll / kqueue / IOCP | 各 OS poll API |
| 機能 | OS API | 意味 |
|---|---|---|
| zero-copy pipe→pipe | splice(2) (Linux) |
観測不要時、コピーゼロで中継 |
| zero-copy file→socket | sendfile(2) |
CPU 1% 未満で大容量転送 |
| pipe 分岐 | tee(2) |
ログ取りに最適 |
| バッチ I/O | io_uring (Linux 5.1+) |
高スループット低レイテンシ |
| pty 完全制御 | posix_openpt 等 |
TTY raw mode / SIGWINCH 中継 |
| cgroup / rlimit | cgroup v2 | 子メモリ上限引き下げ(kill 不要) |
| シグナル順序保証 | signalfd / kqueue |
SIGCHLD と SIGTERM 競合解消 |
.
├── node/ Node.js preload mode 実装
│ └── nproxy.js
├── rs/ Rust CLI relay 実装
│ ├── src/
│ │ ├── main.rs
│ │ ├── relay.rs ← ReadGate + spawn_relay/spawn_text_relay
│ │ ├── memory.rs ← /proc/<pid>/status RSS 監視
│ │ ├── text.rs ← TextPipeline + 状態縮退
│ │ ├── observer.rs ← メタ観測(ring buffer / size / ts)
│ │ └── child.rs ← 子プロセス spawn + signal relay
│ ├── tests/
│ └── Cargo.toml
├── install.sh ヒープサイズ設定インストーラ
├── result/ 旧 Node プロトタイプ一式
├── doc/ 設計ドキュメント
├── README.md ← English
└── README.ja.md ← 日本語 (このファイル)
nproxy は GPL 3.0 のフリーソフトウェアです。 役に立ったと思ったら、任意の暗号通貨支援をお願いします 🙏
Bitcoin: bc1q096t3sc9mndnu94guxcwjqpg7c5qcdv3gf0e0g
ETH: 0x1b9b7911585189c526d7740ce6c5e1c94c78aa84
USDT: 0x1b9b7911585189c526d7740ce6c5e1c94c78aa84
**手数料の関係で最低 $20 以上推奨**
商用ライセンスに関するお問い合わせ(プロプライエタリ利用、OEM 組み込み、カスタム開発): → nproxyinfo@proton.me または GitHub Issues USDT : 0x1b9b7911585189c526d7740ce6c5e1c94c78aa84 ※ウォレットの事情で$20以上から受け付けてます 🙏
---
## コードレビューチェックリスト
ファイル [`REVIEW_CHECKLIST.md`](./REVIEW_CHECKLIST.md) を参照。
レビュー時は以下の観点でチェックする:
- [ ] chunk 非保持 — chunk をフィールド/クロージャに保持していないか
- [ ] backpressure 委譲 — `Poll::Pending` / `ReadStop` / read しない、で止めているか
- [ ] policy 縮退のみ — 本流の停止/拒否が発生していないか