Custodian memory limit accounting varies by Racket backend
0 reputation · 09 Apr 2022, 02:34 UTC
0 reputation · 09 Apr 2022, 02:34 UTC
Designing per-evaluation resource containment in Racket with custodians and racket/sandbox requires a memory cap that reliably triggers an out-of-memory condition inside the contained computation while leaving the host process intact.
The documented mechanism uses custodian-limit-memory and call-with-limits/with-limits. Memory accounting is described as approximate, and allocations shared with the host or outside the custodian may not be charged fully. Time limits depend on wall vs CPU setup and blocking foreign calls may not be interruptible promptly.
An unresolved decision is how limit tuning should account for backend differences. Accounting detail for custodian-limit-memory is reported to differ between the Chez Scheme backend and the legacy BC backend, making a single limit value backend-sensitive.
What documented accounting differences exist between Chez and BC backends for custodian-limit-memory? How should a memory limit be chosen to provide consistent guardrail behavior across backends? Are there documented constraints on what allocations are included or excluded from the custodian charge?
31775 reputation · 09 Apr 2022, 03:11 UTC
Memory accounting for custodian-limit-memory is not identical across Racket backends. The primary difference lies in the granularity and precision of heap tracking between the Chez Scheme and BC backends:
Regardless of the backend, there are documented constraints on what is charged to a custodian's memory limit:
Because the BC backend tends to underestimate usage and Chez is more stringent, a single limit value will behave differently across environments. To provide consistent protection, follow these steps:
custodian-limit-memory for total process safety. Use OS-level limits (e.g., cgroups or ulimit) to protect the host process from foreign memory exhaustion.You can verify the threshold behavior by running a script that allocates large vectors until failure:
(define cust (make-custodian))
(custodian-limit-memory cust 10485760) ; 10MB limit
(custodian-set-current-custodian cust)
(let loop ([acc '()])
(loop (cons (make-vector 1000000) acc)))
Diagnostic Note: To refine this recommendation, please specify if the contained computations rely heavily on ffi calls or if they primarily perform pure Racket heap allocations.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.