You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Robust analysis of memory consumption in Chonk #1641
Where exactly is memory consumed in Chonk. We need an up to date analysis now that the system has largely stabilized. We can use this to determine whether there is any additional work we can do to drive down memory consumption.
Profiled the AMM flow (ecdsar1+amm_add_liquidity_1_recursions+sponsored_fpc, 19 circuits) using BB_POLY_STATS=1. Here's the memory breakdown and where savings opportunities exist.
Overall memory trace (RSS)
Start: 172 MiB (CRS + msgpack parsing)
After EcdsaRAccount (122K): 305 MiB (+133 MiB)
After private_kernel_init (47K): 342 MiB (+37 MiB)
... several small circuits ... 342 MiB (reusing freed memory)
After Token:transfer (180K): 559 MiB (+217 MiB) ← largest circuit
After next kernel_inner: 613 MiB (peak RSS)
RSS is a high-water mark — glibc doesn't return freed pages to the OS. Circuits are processed sequentially; each circuit's ProverInstance is freed after folding. The peak is set by the largest circuit being accumulated.
The Compr(MB) column in BB_POLY_STATS shows ideal compressed size: 11.8 MB vs 82.5 MB actual. Most of the gap is from storing small values (≤4 bytes) in 32-byte Fr elements, and from zero elements still occupying 32 bytes.
Where peak memory occurs
During each circuit's accumulation, the peak is at sumcheck round 0:
Original prover polynomials: 82.5 MB (100%)
+ PartiallyEvaluatedMultivariates: ~41 MB (50%, half-size copy)
= Peak during sumcheck: ~124 MB (150% of polynomial set)
After sumcheck, PEM is freed and batch_polynomials reuses existing polynomial storage (the first polynomial becomes the accumulation target, others are added-scaled into it).
Further savings from run-length encoding or bitmap-based sparse storage
3. Free early, allocate late
Circuit block memory is already freed after copy to prover polynomials (done in chonk::accumulate)
Selectors could potentially be freed after commitment (VK construction) since they're not needed for sumcheck in all flavors — need to check relation dependencies
z_perm, lookup_inverses are allocated but zero until computed — could defer allocation
4. malloc_trim between circuits
Calling malloc_trim(0) after each circuit's fold returns would release freed pages back to OS
Wouldn't reduce peak but would prevent glibc arena inflation from artificially raising RSS
Useful for measurement and for reducing memory pressure on constrained devices
5. Polynomial streaming / on-demand decode
Instead of expand→batch, teach batch_polynomials to read compact sources directly
add_scaled(other, scalar) already reads via other[index] which handles compact mode
Only the accumulation target (first polynomial) needs raw data() — all others can stay compact
@johnathan79717 FYI it seems that some of the changes/optimizations we're considering in the near future may effect the memory behavior a bit, e.g. where the peak lies etc. Just more motivation to think about some kind of tooling to make it easy for us to continually reassess the memory situation in the near term
/claudebox suggest tooling options to make it easy for us to continually reassess the memory situation, especially about the peak memory usage, how high it is, what contributes to the peak, etc.
Activity
johnathan79717 commentedon Mar 5, 2026
Prover memory profile: where the bytes go
Profiled the AMM flow (
ecdsar1+amm_add_liquidity_1_recursions+sponsored_fpc, 19 circuits) usingBB_POLY_STATS=1. Here's the memory breakdown and where savings opportunities exist.Overall memory trace (RSS)
RSS is a high-water mark — glibc doesn't return freed pages to the OS. Circuits are processed sequentially; each circuit's ProverInstance is freed after folding. The peak is set by the largest circuit being accumulated.
Per-polynomial breakdown (EcdsaRAccount, 122K trace, representative)
The
Compr(MB)column in BB_POLY_STATS shows ideal compressed size: 11.8 MB vs 82.5 MB actual. Most of the gap is from storing small values (≤4 bytes) in 32-byte Fr elements, and from zero elements still occupying 32 bytes.Where peak memory occurs
During each circuit's accumulation, the peak is at sumcheck round 0:
After sumcheck, PEM is freed and
batch_polynomialsreuses existing polynomial storage (the first polynomial becomes the accumulation target, others are added-scaled into it).Concrete reduction proposals
1. Compact sigma/id storage (uint32_t compression) — WIP in PR #21124
Polynomial::operator[]returningFrby value2. Sparse/zero-aware allocation
3. Free early, allocate late
4.
malloc_trimbetween circuitsmalloc_trim(0)after each circuit's fold returns would release freed pages back to OS5. Polynomial streaming / on-demand decode
batch_polynomialsto read compact sources directlyadd_scaled(other, scalar)already reads viaother[index]which handles compact modedata()— all others can stay compactledwards2225 commentedon Mar 9, 2026
@johnathan79717 FYI it seems that some of the changes/optimizations we're considering in the near future may effect the memory behavior a bit, e.g. where the peak lies etc. Just more motivation to think about some kind of tooling to make it easy for us to continually reassess the memory situation in the near term
johnathan79717 commentedon Mar 27, 2026
/claudebox suggest tooling options to make it easy for us to continually reassess the memory situation, especially about the peak memory usage, how high it is, what contributes to the peak, etc.
AztecBot commentedon Mar 27, 2026
ClaudeBox: suggest tooling options to make it easy for us to continually reassess the memory situation, especially about the peak m ... workflow run
feat: add --memory_profile_out flag for Chonk memory profiling
feat: add plot_memory.py for visual RSS timeline of bb prove runs
feat: add --memory_profile_out flag for Chonk memory profiling (#22145)
feat: switch memory profiling from peak RSS to live heap usage (#22229)
feat: switch memory profiling from peak RSS to live heap usage (#22266)