Repository navigation
[0.32][Research] Find remaining ELF/cycle costs and measure the optimization frontier #40
Description
Accepted scope update — 2026-10-03
The maintainer authorized completion of the 0.32-related issues, including #36–#39 and #22. Independent review is waived for this work; no independent review is claimed. The earlier per-slice requirement for an independent boundary reviewer is superseded by that decision. Frozen budgets, compiler/checker agreement, adversarial execution evidence and final backend/CI gates remain required. This is not release or deployment authorization.
Implementation and acceptance are in progress. Existing checkboxes below remain authoritative for unfinished work.
Objective
Find the byte and execution costs that remain after 0.31, explain where they come from, and test how far they can be reduced while preserving the admitted contract semantics and independent artifact checking.
The deliverable is a measured set of implementation decisions and follow-up changes. Treat "as small and cheap as possible" as a search objective: publish the best measured alternatives for ELF size and execution cycles, including their tradeoffs. Do not claim a global optimum from a finite benchmark corpus.
Version assignment — 2026-09-24
Target: 0.32 research and optimization planning. This issue does not block 0.31.
- 0.31: keep the accepted feature scope frozen. Finish independent boundary review, coordinated versions, fresh WASM/editor bundles and the full release gate under [0.31][Cost] Track abstraction-cost optimization and required design decisions #30. Fix correctness defects and cost regressions found during acceptance; do not add the experiments from this issue to its release requirements.
- 0.32: begin with clean-baseline reproduction and cost attribution, then select the best-supported experiments from [Post-0.31][Backend] Evaluate policy dispatch alternatives with measured crossover evidence #37–[0.32][Backend] Evaluate register retention and helper scratch reuse #39 and the additional tracks below. Record explicit adopt/reject/defer decisions and acceptance budgets. The milestone assigns the research work; it does not promise delivery of every proposed optimization.
- Compressed instructions and wire-format changes: require separate design decisions and compatibility evidence. They may be investigated during 0.32, but implementation is not committed to that release.
- Research can start now on separate experimental branches without expanding or delaying the 0.31 release. This umbrella coordinates [Post-0.31][Cost] Measure observed per-VM stack high-water marks #36–[0.32][Backend] Evaluate register retention and helper scratch reuse #39; those issues remain candidate work until their individual implementation scope is accepted.
Starting evidence
Use commit 6196a7fc60c5186240e3e9acf31bed2b764a580e as the source starting point. Its reproduction package contains exact source replay patches and the archived report pairs. Those measurements declare dirty, reconstructible source snapshots; the packaging commit must not be presented as their original measured clean commit. Produce a fresh clean-commit baseline for this research.
The archived comparator passes 6,782 comparable metrics without a regression. That establishes the specified comparisons, not that further savings are exhausted.
Concrete remaining questions:
- All nine scalar fixtures retain the same static store count.
scalar-overlap-260has 529 stores before and after slot reuse; its loads change only from 820 to 818. These are whole-text instruction counts, not executed accesses or proof that the instructions are redundant. - Policy dispatch still scans tags linearly. Private argument copies and outer witness normalization remain. These were deliberate 0.31 exclusions.
- The scalar allocator has conservative whole-function exclusions, and spills all parameters into distinct slots. Measure the coverage and cost of those fallbacks before relaxing them.
- The immediate planner chooses between validated constructions and a fallback. Its tests establish correctness over the tested cases and no growth relative to the fallback; they do not establish shortest sequences over every legal encoding.
- The ELF writer already uses 128-byte segment alignment. The old 3,976-byte padding removal has already happened and must not be counted as future savings.
- The standalone decoder walks four-byte instructions and requires four-byte control-flow alignment. Compressed encodings would change this boundary substantially.
1. Attribute the remaining cost before choosing transformations
Build a per-artifact and per-execution breakdown:
| Quantity | Required distinction |
|---|---|
| Deployed ELF bytes | Headers, padding, executable text, read-only data, and other retained sections; totals reconcile with file length |
| Generated text | Entry/witness loading, tag dispatch, decoder, direct stubs, action bodies, helpers, and error paths; count shared code once |
| Executed work | Instruction classes, load/store accesses, copied bytes, branch/call frequency, and syscall counts/charges, with VM/process identity |
| Cycles | Transaction success, individual Script-group success/rejection, and unavailable outcomes; preserve the existing oracle |
| Other costs | Witness and full transaction bytes; static stack bounds and observed per-VM stack peaks remain distinct |
Use #36 for observed stack instrumentation. Extend measurement deliberately for executed memory traffic and per-PC cost attribution, with a versioned report contract and tests against small hand-calculated programs. A host execution trace is diagnostic: demonstrate that instrumentation does not change the artifact's verdict or authoritative cycle total. Account for additional syscall charges and process scheduling explicitly; do not assume an instruction histogram alone explains the full transaction cost.
The pinned CKB-VM 0.24.14 cost model assigns different costs to instruction classes. Fewer instructions or fewer ELF bytes therefore do not, by themselves, establish fewer cycles. Bind the actual node/VM versions and enabled instruction behavior in every experiment.
Separate unavoidable work required by the selected contract from implementation overhead. State assumptions behind any proposed lower bound. Identify the hottest executed sites and largest repeated code regions, then rank experiments by measured opportunity and verification effort.
2. Experiments and decisions
Every row below is a hypothesis to test, not an implementation claim or an accepted optimization.
| Track | First experiment | Decision required |
|---|---|---|
| Register retention / spills — #39 | Retain eligible scalar values within a basic block; remove demonstrably dead spills/reloads; classify parameter spills and allocator fallbacks | Exact helper/call clobbers, live-register ownership, address-exposed exclusions, flush rules at joins/calls, and whether any wider allocator is justified |
| Dispatch — #37 | Compare current linear routing with saved-selector routing and bounded comparison trees on the existing dense/sparse/high-u32 matrix | Measured thresholds, tie-breaking, selector lifetime, exact target-set checks, and whether a jump table warrants a separate design |
| Witness loading and copies — #38 | Measure normalization, parent-to-adapter copying and syscall work independently; test borrowing, bounded word copies, and staged loading separately | Ownership, overlap, alignment, tail safety, buffer lifetime, nested/outgoing calls, and preservation of the complete admitted witness set |
| Repeated code and specialization | Attribute repeated helpers, decoder tails, errors and generic instantiations; compare bounded outlining, inlining and specialization choices | Complete equivalence keys, call overhead, source/proof attribution, and specialization limits; retain runtime checks whose redundancy is not established |
| Pure IR and CFG simplification | Audit existing constant folding, inlining and dead-code passes first; prototype missed pure common expressions, redundant stack traffic, and branch simplifications | Which effects, traps, overflows, resource operations and error-order dependencies prohibit rewriting; how eliminated checks remain justified |
| Immediate and address construction | Search bounded literal domains and real emitted constants for shorter legal sequences; compare rematerialization with reuse or constant-pool loads | Explicit search grammar/bounds, register pressure, pool bytes/relocations, branch relaxation, and instruction-set scope; distinguish a proved bounded result from sampled evidence |
| ELF and data layout | Inventory remaining section/padding/string/constant costs and test legal deduplication/layout changes | Loader and independent-checker requirements, exact accounting, deterministic output, and whether a format change is worth its compatibility cost |
| Compressed instruction feasibility | Count actually encodable sites using their real registers/immediates; construct a small isolated mixed-width prototype only after target verification | Pinned CKB support, a bounded instruction subset, assembler sizing/relaxation, decoder/control-flow alignment, source maps and versioned checker migration |
For compressed instructions, the RISC-V C specification describes 16-bit encodings with operand restrictions. Its general code-size estimates are not CellScript measurements. First verify the exact supported CKB target; do not enable compressed instructions in the current production backend merely because the ISA has them. Measure whole-ELF effects after relaxation/alignment and authoritative cycles separately.
Witness/ABI redesign is a separate compatibility track. If the byte breakdown justifies one, propose a versioned format, canonical codec, migration rules and builder/checker changes in its own RFC. Keep the existing wire format as the baseline. Archive compression of release downloads does not reduce the deployed executable by itself; a runtime unpacking design would need its own measured execution and verification contract.
3. Experimental design
- Reproduce the current baseline with exact compiler/checker commits, source and ELF hashes, dependencies, toolchain, strip tool, profiles, target and VM configuration. Keep Cargo build directories isolated between source checkouts.
- Retain all existing matched Rust samples, 18 growth rows, 41 expanded policy rows, nine scalar/call fixtures, every action/rejection observation, and six multi-Script cases. Preserve fixed budgets and measurement availability rules.
- Add focused probes before tuning: repeated versus distinct generic instantiations; non-overlapping versus simultaneously live scalars; joins/backedges/calls; immediate, offset and branch-distance boundaries; first/last/unknown tags; exact/truncated/over-bound witnesses and malformed late records. Include held-out application-shaped fixtures so gains are not confined to a synthetic pattern.
- Run one transformation at a time. After individual results, test interactions: register retention × outlining, slot placement × compressed eligibility, dispatch × immediates, borrowing × nested calls, and code layout × branch relaxation. Re-measure the combined candidate rather than adding isolated savings.
- Keep current Rust references unchanged for continuity. Add further matched Rust examples where coverage is missing, with equivalent checks and accepted/rejected inputs. Record ISA, build and stripping differences explicitly. Any separately retuned Rust reference must be labeled and retained alongside the old reference.
- Publish raw artifacts, source replay/clean identities, per-fixture deltas and rejected experiments. Include all exercised rejection paths and worst observed rows. Label a corpus maximum as observed, not a bound over all possible inputs.
4. How to choose the result
Maintain the non-dominated alternatives: a candidate belongs on the measured frontier when another tested candidate does not improve it across all the chosen cost dimensions. Keep per-fixture results visible; a single average can hide a regression.
- The default production candidate must preserve existing ceilings and comparable outcomes. Keep the existing no-regression rule unless an exact, documented tradeoff is accepted by the maintainer and compiler/checker boundary reviewer.
- Decide whether the evidence warrants separate size-oriented and cycle-oriented profiles. These are proposed policies, not new CLI flags promised by this issue. Any accepted profile needs deterministic selection, explicit budgets and the same semantic contract.
- Do not preselect a dispatch threshold, savings percentage or code-size/cycle exchange rate. Reject experiments that save too little to justify their checker/maintenance cost, and retain the measurements explaining that decision.
- Keep source editions, Cell/resource lifecycle rules, admitted inputs, witness ownership, error propagation and external-verifier trust boundaries fixed in the initial experiments. Any proposed semantic or wire change gets a separate decision.
- Changed machine shapes require coordinated lowering/source-map/checker updates, negative mutations and regenerated artifact identities. Compiler self-checks alone are insufficient. Existing deployments retain their old identities.
Work order and completion
Start with attribution and clean baseline reproduction, then prioritize #39, #37 and #38 using that evidence. Run code-sharing/pure-IR/immediate probes next. Treat compressed instructions and wire changes as separately gated investigations. Each implementation slice must name an implementer, an independent boundary reviewer, its target fixtures and acceptance budget before merge.
- Publish an inventory marking each opportunity as already implemented, unfinished, excluded for a stated reason, or unmeasured. Link each item to code and owning issue.
- Produce reproducible byte and execution-cost attribution, with explicit coverage and unavailable categories.
- Give every experiment above an adopt/reject/defer decision supported by results or a concrete blocker; create narrowly scoped implementation issues where needed.
- Publish the measured frontier and select the default/profile policy with recorded tradeoffs.
- Test selected transformations together and preserve the baseline/Rust/adversarial comparisons without regenerating budgets to make them pass.
- Update independent machine contracts and mutation tests for accepted backend changes; pass
./scripts/cellscript_gate.sh backendand./scripts/cellscript_gate.sh ci. Use the full release gate and fresh downstream bundles before publication. - Finish with a residual-cost report: what remains, why it remains, which search spaces were exhausted under stated bounds, and which remain untested. Completion means the agreed research questions are answered and implementation work is explicitly tracked; it does not mean universal optimality has been proved.
Activity
[-][Post-0.31][Research] Find remaining ELF/cycle costs and measure the optimization frontier[/-][+][0.32][Research] Find remaining ELF/cycle costs and measure the optimization frontier[/+]a19q3 commentedon Sep 27, 2026
Accepted immediate-construction slice: #41, implemented on
0.32at 8017a7bd.Decision: adopt the validated low-mask candidate only on a strict improvement. Constructing
2^n - 1for n=31..63 now usesaddi rd, zero, -1; srli rd, rd, 64-n: two real instructions instead of three, with the same result and no extra register. Existing shorter/equal plans remain unchanged.The archived evidence binds clean baseline
54d639a7and clean implementation0e544ce1, passes 6,782 comparable metrics without regression, and retains the raw report pairs and checksums. The focused executed saving is four instruction bytes and one cycle per materialization. Whole-program gains are small and fixture-specific; alignment can absorb the file-size saving.This does not select general immediate search, register retention, dispatch redesign, witness changes, compressed instructions, or any other candidate from this umbrella. 0.30/0.31 remain unchanged. Final gate receipts are tracked in #41. Implementation-author engineering evidence does not substitute for the independent boundary review required before merge or for release approval.
a19q3 commentedon Oct 5, 2026
0.32 research closure progress; this issue remains open while the final #39 archive and decision update are published.
The published research report retains the clean baseline, 1,707-run attribution, measured frontier, residual sites and historical gate identities. #36, #37 and #38 are now closed with individual evidence comments. Their outcomes are measured instrumentation or explicit retain/reject/defer decisions, not automatic adoption of every proposed optimization.
#39's second bounded candidate was measured locally and rejected: four of 1,707 executions save one cycle, without ELF/store/stack savings. Its exact source replay and raw reports are prepared for publication. No register-retention change was applied to the default backend.
The current implementation's comparison with the published cost baseline still passes all 6,782 comparable metrics with unchanged budgets and Rust references. Wider CSE, outlining, constant-pool search, borrowing and compressed instructions retain their explicit semantic/checker blockers; a finite evaluation does not claim those transformations are implemented or universally unhelpful.
Validation boundaries remain explicit. The historical clean research baseline has archived backend/CI passes. The latest interface/entry-scoping work for #28 passed compiler/checker tests, Clippy, cost comparison and the full syntax matrix, but its complete backend gate stopped at the stateful harness's clean-committed-source prerequisite. It has no new full backend-pass claim until that replay completes. Release publication and public deployment remain separate.
a19q3 commentedon Oct 10, 2026
Completed within the 0.32 implementation scope. This closes the 0.32 cost research umbrella: clean baseline, cost attribution, per-track adopt/reject/defer decisions, measured frontier and residual report are published in RESEARCH.md. This is not a release/public-deployment claim and does not claim global optimality from the finite corpus.
backend(including pinned CKB stateful acceptance) andcipass at clean6a453d3015784784a27ba1aa0a4b6b1a73db79a8, archived with logs in validation.json. The full release gate and fresh downstream bundles belong to the separate 0.32 release process, not to this research closure.#36–#39 now carry individual closure evidence on their issues. Closing this umbrella answers the agreed research questions with implementation work explicitly tracked; it does not convert unmeasured transformations into rejected experiments or implemented features.
a19q3 commentedon Oct 10, 2026
Closing as completed: attribution, per-track decisions, measured frontier and residual report published; default policy selected. Evidence: #issuecomment-6099391394. Sub-coordination issues #36–#39 are closed individually.
docs: record #39/#40 closure evidence links in 0.32 implementation map