One-shot Pyodide executions retain a high sidecar memory watermark after VM disposal
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 35/100
- issue の種類
- バグ
- 明瞭さ
- おおむね明確
- 活発さ
- 静か
- 技術スタック
- javascript, python, rust, wasm
- 領域
- backend, performance, testing-qa
調査の方向性
まず crates/execution/src/python.rs、crates/execution/src/javascript.rs、assets/runners/python-runner.mjs、crates/native-sidecar/tests/python.rs を読んでください。PSS/RSS とライフサイクルメトリクスを記録しながら、標準ライブラリ、NumPy、pandas の実行を繰り返して dedicated-sidecar probe を実行してください。メモリが有界なプラトーに達するかどうかを確立するか、サポートされる解放境界を定義して本番戦略を文書化すれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Summary
Repeated one-shot Python executions substantially raise the shared native sidecar's proportional set size (PSS). Waiting for each execution, disposing its VM, deleting its persisted workspace, and waiting five seconds does not return the sidecar close to its cold memory footprint. Exiting the sidecar process does.
A fresh-process staged probe suggests a retained/high-watermark behavior rather than enough evidence for an unbounded linear leak:
- cold sidecar: ~18 MiB PSS
- standard-library Python, after 5 isolated executions: ~270 MiB
- NumPy, after 8 additional isolated executions: ~422 MiB
- pandas, across 8 additional isolated executions: ~445–558 MiB, non-monotonic
The pandas stage sometimes drops by ~80 MiB, so this issue intentionally does not claim that every execution permanently leaks a fixed amount. The operational problem is that VM disposal is not currently a reliable physical-memory reclamation boundary for one-shot Pyodide workloads in a long-lived shared sidecar.
Environment
@rivet-dev/agentos:0.2.16-rc.1- Node.js:
v22.22.2 - OS: Linux x86_64, kernel
6.6.98 - glibc:
2.38 - sidecar placement: shared process
- Python mode: one-shot
vm.python.spawn, not retained contexts - packages: Pyodide-provided NumPy and pandas assets
Probe procedure
The probe starts a fresh Runtime/native sidecar and records Linux PSS from /proc/<sidecar-pid>/smaps_rollup.
For every iteration it:
- creates a new VM/workspace;
- calls
vm.python.spawn(...); - waits for the execution to finish;
- disposes the VM;
- deletes the workspace SQLite files;
- waits 5 seconds;
- records sidecar PSS.
Workloads are executed sequentially in this order:
cold baseline
standard library x5
NumPy x8
pandas x8
Each execution uses a distinct VM. There are no retained Python contexts.
Results
PSS values are KiB:
baseline 0 18,374
stdlib 1 241,806
stdlib 2 263,672
stdlib 3 269,970
stdlib 4 270,846
stdlib 5 276,930
numpy 1 356,644
numpy 2 372,698
numpy 3 397,170
numpy 4 412,674
numpy 5 413,298
numpy 6 416,974
numpy 7 420,218
numpy 8 421,774
pandas 1 558,232
pandas 2 527,151
pandas 3 444,790
pandas 4 461,963
pandas 5 476,763
pandas 6 486,619
pandas 7 539,143
pandas 8 461,629
Execution times were approximately 19–23 seconds for standard-library/NumPy runs and 26–30 seconds for pandas runs.
A separate already-warm probe started around 971 MiB PSS and reached approximately 1,162 MiB after three NumPy+pandas executions, despite deleting each workspace and waiting after each run. Restarting the Runtime/sidecar returned it to approximately 31 MiB.
File descriptors returned to the baseline range, and deleting SQLite/workspace files did not lower PSS. The memory belongs to the native sidecar process rather than the Node host process.
Expected behavior / requested contract
Returning exactly to cold PSS after every execution may be unrealistic for V8, Pyodide, WebAssembly memories, and the native allocator. What is needed for a long-lived shared sidecar is one of:
- repeated identical one-shot workloads reach a documented, bounded plateau after VM/context disposal; or
- AgentOS exposes a supported reclamation/lifecycle boundary that releases Python runtime memory without terminating unrelated VMs in the shared sidecar.
At minimum, it would be useful to document the expected memory lifecycle and recommended production strategy.
Suspected boundary
Python runs inside the shared sidecar approximately as:
native sidecar
-> V8 session
-> Pyodide
-> WebAssembly linear memory / ArrayBuffer backing stores
-> NumPy / pandas
AgentOS has context/VM disposal paths and removes logical tracking state, but logical disposal does not demonstrate that V8 sessions, WASM backing stores, or allocator arenas are released or returned to Linux.
Possible causes include:
- disposed V8/Pyodide objects still being referenced;
- delayed collection of WASM/ArrayBuffer backing stores;
- native allocator arenas retaining released pages;
- a combination of these.
The non-monotonic pandas measurements make allocator/runtime high-watermark retention the leading explanation, but a longer 30–100 iteration low-point slope is needed to rule out an unbounded component.
Potentially relevant source areas:
crates/execution/src/python.rscrates/execution/src/javascript.rscrates/execution/assets/runners/python-runner.mjscrates/native-sidecar/tests/python.rs
The Python integration tests also note shared-process teardown/init instability for V8/Pyodide-backed cases and process-global Pyodide module state, which may be relevant to defining the supported lifecycle.
Suggested regression / diagnostics
A useful upstream regression would run in a dedicated sidecar OS process:
cold start
standard library x10
NumPy x30
pandas x30
For every iteration:
- wait for one-shot execution completion;
- dispose context and VM;
- wait a fixed settle period;
- record PSS/RSS/private dirty, active VM/process/context counts, and V8/WASM memory metrics.
After discarding package materialization/warm-up iterations, evaluate the slope of local PSS minima rather than requiring memory to return to cold baseline. Heap/allocation profiling could then distinguish reachable V8 sessions, retained WASM backing stores, Rust/JS tracking objects, and allocator-only retention.
Why this matters
A shared sidecar can serve many independent VMs. If the reliable physical reclamation boundary is the sidecar process rather than the VM, operators need to drain and restart the entire sidecar based on memory thresholds, affecting unrelated sessions. A bounded per-VM or Python-runtime reclamation boundary would avoid that operational coupling.
- 主要言語
- Rust
- スター
- 4.7k
- フォーク
- 263
- 平均マージ
- 9時間 43分
- マージ済み PR(30日)
- 27
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
rivet-dev/agentos のほかの issue
-
Python edits to filesystem.writeFile-created files are reverted by shadow reconciliation対応中かも @ankssjain が 2 日前に担当しました。 オープン
難易度 4/5 3〜5日 初心者へのやさしさ 20/100
rivet-dev/agentos#2022 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 3/5 半日 初心者へのやさしさ 32/100
メンテナーはふだん 1 日以内に返信
-
Python launched through guest shell stalls on queued filesystem RPCs対応中かも @ankssjain が 8 日前に担当しました。 オープン
難易度 4/5 3〜5日 初心者へのやさしさ 52/100
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 45/100
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 66/100
rivet-dev/agentos#1994 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
rivet-dev/agentos の issue をすべて見る
似ている issue
-
documentation enhancement
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
adorsys/status-list-server#619 ·
メンテナーはふだん 2 日以内に返信
-
batch-backport only backports the first 30 matching PRs対応中かも @DvirDukhan が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 5 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 77/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
equinor/septic-config-generator#481 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
メンテナーはふだん 1 日以内に返信