Problem
The RLIMIT_AS default was hardcoded at 200 MB and worked fine on Python 3.11, but Python 3.12's higher baseline VM usage made the limit too tight (#20). We fixed it by bumping to 512 MB, but the same drift will likely recur on 3.13 or 3.14 — each CPython release tends to grow baseline memory slightly.
Proposal
At app startup (before any /execute requests), measure the current interpreter's baseline virtual memory size and compute RLIMIT_AS dynamically:
rlimit_as = baseline_vm + user_budget
Where user_budget is the configurable part (what we actually want to cap user code at — e.g., 400 MB). The baseline measurement absorbs interpreter version drift automatically.
Measurement approach
On Linux, read /proc/self/status → VmSize at startup. This gives the parent process's virtual memory footprint before any user code runs. The subprocess inherits a similar baseline (it's a fork/exec of the same interpreter), so using the parent's measurement as an approximation is reasonable.
def _measure_baseline_vm_kb() -> int:
with open("/proc/self/status") as f:
for line in f:
if line.startswith("VmSize:"):
return int(line.split()[1]) # kB
raise RuntimeError("Could not read VmSize from /proc/self/status")
Fallback
If /proc/self/status isn't available (macOS dev, non-Linux CI), fall back to the current hardcoded default. This keeps local development working without Linux-specific dependencies.
Context
Follow-up from #20 review. Not urgent — the 512 MB default works today — but worth doing before the next CPython version bump.
Problem
The RLIMIT_AS default was hardcoded at 200 MB and worked fine on Python 3.11, but Python 3.12's higher baseline VM usage made the limit too tight (#20). We fixed it by bumping to 512 MB, but the same drift will likely recur on 3.13 or 3.14 — each CPython release tends to grow baseline memory slightly.
Proposal
At app startup (before any
/executerequests), measure the current interpreter's baseline virtual memory size and compute RLIMIT_AS dynamically:Where
user_budgetis the configurable part (what we actually want to cap user code at — e.g., 400 MB). The baseline measurement absorbs interpreter version drift automatically.Measurement approach
On Linux, read
/proc/self/status→VmSizeat startup. This gives the parent process's virtual memory footprint before any user code runs. The subprocess inherits a similar baseline (it's a fork/exec of the same interpreter), so using the parent's measurement as an approximation is reasonable.Fallback
If
/proc/self/statusisn't available (macOS dev, non-Linux CI), fall back to the current hardcoded default. This keeps local development working without Linux-specific dependencies.Context
Follow-up from #20 review. Not urgent — the 512 MB default works today — but worth doing before the next CPython version bump.