chore(B7): defer plan; tuple cost crossover makes large tables a regression#231
Merged
Conversation
…ession PR #229 implemented the full plan and passed correctness, but multi-n measurement on the bench harness from PR #230 revealed that wins at n<=100 (-14% to -21%) are accompanied by losses at n=1000 (+30% to +40%), plus 3-5x memory regression at the same scale. The crossover is structural: setelement/3 on a 1024-cell tuple copies the whole tuple every write, vs Map.put's amortized log-time tree allocation. PUC-Lua avoids this with in-place C mutation; we can't. A future plan could revisit this with threshold-based promotion (stay in the data map until array_len reaches some boundary, then promote). That would preserve the small-table wins without the large-table hit. Until that plan exists, table workloads have to look elsewhere for durable wins (likely B5: compile prototypes to Erlang). Plan file updated with full measurement data and the conditions under which the work could be reopened. PR #229 closed without merging.
This was referenced May 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Defer B7: tuple cost crossover makes large tables a regression
Updates
.agents/plans/B7-table-array-hash-split.mdfromready→deferredwith the measurement data that drove the decision to close PR #229 without merging.Why we closed #229
#229 implemented the full plan correctly (all 1692 tests + 29 lua53 suite tests passed). But when we re-measured under the bench harness from #230 with multi-n inputs, the picture changed:
Memory regressed 3-5× at n=1000 (Sort: 2.08 MB → 12.40 MB).
The crossover is structural: BEAM tuples are immutable, so every
setelement/3on a 1024-cell tuple copies the whole tuple. PUC-Lua avoids this with in-place C mutation; we can't. Small n wins becausesetelement/3's constant-factor advantage overMap.putmatters; large n loses because copying dominates.The single n=500 measurement that originally motivated B7 was right at the crossover. Multi-n in #230 was what made the pattern visible.
Conditions for reconsidering
A future plan could revisit this with threshold-based promotion: keep contiguous integer keys in the hash map until
array_lenreaches some boundary (e.g. 256), then promote. That would preserve the small-table wins (-14% to -21%) without taking the large-table hit. The plan file documents what such a plan would need to address.Until that plan exists and ships, table workloads have to look elsewhere for durable wins — likely B5 (compile prototypes to Erlang) which attacks
setelement/3register-write cost directly.Changes
Only the plan file changes; no library code touched.
Verification
(All trivially pass; this PR only edits a plan file.)