fix(cdp): cap glibc malloc arenas so memory does not track peak concurrency
glibc hands each new thread its own 64 MiB arena (up to 8x cores). With one thread per connection that arena is the dominant per-connection memory term, and freed chunks stay reserved in it rather than returning to the OS: resident memory tracks the *peak* number of concurrent connections and never comes back down, which reads as a leak although nothing is leaked and no thread is stuck. Measured with reliability/conn-scale.py in obscura-benchmark. 100 connections each running JS reserve 90.0 GiB of address space uncapped versus 83.5 GiB capped; per idle connection, 65 MiB of reserved address space drops to 2.0 MiB. `main` at that same 100-connection JS workload reserves 83.6 GiB, so with the cap this server is level with it -- most of the total is V8's process-wide sandbox, which `main` pays too the moment it runs any JS. The resident-set effect is the one that bites in production. Measured in the container image against Google Maps, four concurrent connections per round: 350 / 619 / 826 MiB over three rounds uncapped and still climbing linearly, versus 166 / 235 / 269 MiB capped, on a decelerating curve. Two arenas cost no measurable throughput here -- 8 concurrent connections x 12 navigations, 1.53s uncapped against 1.50s capped over three runs. V8 allocates the JS heap through its own allocator and the Rust side is dominated by network I/O rather than malloc traffic. Applied only from `serve`, which owns the process, and skipped when the caller has already set MALLOC_ARENA_MAX. Refs #430.
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1664,6 +1664,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
"futures-util",
|
||||
"libc",
|
||||
"obscura-browser",
|
||||
"obscura-dom",
|
||||
"obscura-js",
|
||||
|
||||
Reference in New Issue
Block a user