Repository navigation
perf(c): build lists directly from flat arrays - #2012
vicmcorrea wants to merge 2 commits into
Conversation
|
Thanks for picking this up, and for crediting the report. I won't open a second PR for #1991; this one is the flat walk I had in mind. You listed Linux and CUDA as not qualified, so I ran the PR head (f27fd28) against its base (db64cf7) here: Core Ultra 7 155H, Linux, clang 23.1.3, RTX 4050 with CUDA 13.4.
All print 23.789732. So on x86 it's 5.7x fewer instructions and 3.4x less time (cycles go from 3,972 M to 1,118 M), and One thing to be upfront about: my own packages don't call |
Problem and fix
Array.to_listrecursively splits native flat storage, allocating and copying halves before building the list. This implements a C lowering for checked instances of Base'sArray.to_list.go, using nuxyel's workload from #1991.Walk cells backward into the supplied suffix, transferring owned values or retaining shared boxed fields, then release the source block. Reuse the existing layouts, constructor builder, sharing facts and device error poll.
Six alternating one-thread runs per version of the reported 64 × 2²⁰ F32 fill/convert/sum workload, macOS M1 Pro, clang 23.1.4
-O3:db64cf7Every run prints
23.789732. These measure the whole workload, including allocation and summation. Wall time varies with host activity.Blast radius
The change adds 23 lines in
bend2/comp.tsand two compiler fixtures. Only Base's recorded helper specializations receive this C lowering. Base definitions and the JS reference runtime are unchanged. No-use controls emit byte-identical C, including device input.There is no public API change. The source block stays live until the list is built. For an owned singleton with two Nat fields, the observed class-1 order changes from
free, allocate, allocatetoallocate, allocate, free, briefly retaining two extra words. Ten million such conversions retired 5% more instructions, with median CPU time 0.16 → 0.14 s.Regression evidence
Fixtures cover order, packed and padded values, shared boxed ownership, affine closures, partial application, Unit, a supplied suffix, and conversions in the leaves of a banged fork tree. Behavioral output agrees with main. Removing the shared Shape-field retain produces a memory fault in all three poison runs. The intact implementation passes.
Actual heap hooks on eight F32 cells observe 12 class-0 and 10 class-1 allocations on main, versus eight class-1 list allocations here. The new trace frees the original class-2 block after those list nodes; it does not allocate intermediate array halves.
Checks
0ba4e5ewith comp.ts: a fact stales only the units that read it absent #1601 (2069445) and perf(c): blk_new fills whole elements, clones keep runs; JS shares the cell depth wall #1946 (b3521c9) pass all four direct consumers through source execution, Bun JS and native C with heap poison, ASan and UBSan. comp.ts: a fact stales only the units that read it absent #1601 needs one textual resolution aroundc_units; perf(c): blk_new fills whole elements, clones keep runs; JS shares the cell depth wall #1946 applies cleanly.0ba4e5epasses the four direct consumers through source execution, Bun JS and native C with heap poison, ASan and UBSan. Its four emitted C files are byte-identical to this tested head; emitted JS incorporates the upstream timer and F32 changes.git diff --checkpasses.Validation limits
Compiler budget blocks merge: the submitted head is 66,372 / 66,000 ttok, so hosted CI remains 53/54. A private combination of the unchanged patch with main
0ba4e5eis 66,277 / 66,000; the new upstream cleanup still leaves 277 tokens over the cap. No cap changes or unrelated trimming are included, following the scoped-feature guidance in #1820.The full test gate cannot reach the unresolved
clusterhostname. Local execution used macOS. Linux and CUDA evidence above is contributor-reported. Windows, concurrent alias mutation and dedicated leak stress remain unqualified. Typechecking matched the seven diagnostics of the testeddb64cf7baseline in the protected checker and documentation tools, with none incomp.ts.The issue reporter confirmed this implements the intended flat walk and will not open a competing PR. The earlier JS flat-walk proposal was withdrawn.
Pending #2017 changes the same
c_unitsbranch and would require a textual resolution if it lands first. Its HID feature is separate from this lowering. Pending #2019 introduces host array views and explicitly leaves #1991 to a flat walk.