Repository navigation
fix(runtime): reclaim native channel rows and unread buffered values - #1532
Lorenzobattistela merged 4 commits into
Conversation
|
Thanks, this fixes #1268: 500k buffered send/close goes from 34.5 MB to 1.6 MB here. The 17M-iteration loop no longer stops at "more than 16777216 channels", and never-closed channels are reclaimed too. One bug: a return rfc_wrap(e, term_blk(true, cls, loc), 1);Please add a test for that case (a channel in a shared list cell). Also, both new tests pass on main, so neither would catch a revert of this fix. Smaller things:
|
…thub.com/oxura/bend into fix/issue-1268-channel-lifetime-20261012 # Conflicts: # bend2/effs/chan.c
|
Published a781bf7. Your d95603c arrived while I was pushing the same RFC fix; I merged and preserved it rather than overwriting the branch. I retained your tests/io/chan_shared_node.bend and removed my overlapping shared-list fixture. Your retained fixture prints 78end on rebuilt native binaries at 1/4 threads, the interpreter and emitted JS. My separate before-fix shared-list probe had reproduced runtime fail-stop, so the regression was observed, not inferred from green gates. Added a reclamation regression that fails on original main rather than only covering old behavior: tests/io/chan_reclaim_limit.bend creates and discards 16,777,217 never-explicitly-closed handles. Original main exits 1 with “more than 16777216 channels at once” (788,152 KiB peak RSS); the patched native run prints done (2,228 KiB; 1.23s) and emitted JS prints done (3.10s). These are single Linux samples, not timing/RSS assertions in the test. The ordinary interpreter run also prints done. This checks the removed process-wide lifetime limit without a platform-dependent RSS threshold. Rebuilt and exercised all 26 existing native channel/fiber consumer runs at 1/4 threads, including the expected closed-join and deadlock errors. Repo gate: 54/54. Added braces to the three one-line ifs and corrected the header/foreign-representation documentation. Agreed on the remaining limits: the earlier ASan runs cover ordinary allocations such as waiter timers, not Bend heap bounds or row/node reclamation. Your channel-only 6–13% slowdown is a maintainer measurement, not a general speedup claim; I am adding both that cost and the absence of a channel perf bench to the PR description. No GPU, Mac or mini-cluster run claimed. |
Fixes #1268. Native Chan is now an owned heap row with an owned FIFO of two-Term nodes, using existing ARR reference counting and iterative term_drop. The global row table, generation handles and deferred row recycling are removed. Each effect consumes its handle; parked operations retain it until wake/deadline. Close still wakes waiters and preserves buffered FIFO contents for copied handles. Receiving transfers a value out, and a full-channel dequeue reuses its node when waking a queued sender. Capacity is logical: creating a channel no longer reserves/touches a capacity-sized ring. No new runtime tag, finalizer framework or garbage collector.
Actual Linux/clang 22.1.8 verification:
There is deliberately no permanent RSS threshold: standalone before/after/control measurements prove reclamation; deterministic regressions cover ownership transitions without depending on platform RSS or sanitizer overhead. Native Chan's opaque foreign representation changes, documented in EFFECTS; foreign effects already have no ABI promise. Lifetime follows the existing native reference-counting model, not tracing collection of cycles. No Metal/CUDA run is claimed.
Review follow-up (a781bf7)
Preserved maintainer d95603c: Chan handles are born RFC-wrapped so sharing a Data container does not fail-stop. The retained chan_shared_node fixture prints 78end on actual native 1/4-thread runs, interpreter and emitted JS. Rebuilt 26 existing native channel/fiber consumer runs pass their success/error contracts. Repo gate passes 54/54.
Added chan_reclaim_limit.bend: 16,777,217 discarded, never-explicitly-closed handles. Original main fails with the old lifetime-limit diagnostic; after-fix native and JS print done. Single Linux samples: native 1.23s / 2,228 KiB peak RSS, emitted JS 3.10s. Neither timing nor RSS is a permanent assertion.
Tradeoff: maintainer measurements show channel-only loops 6–13% slower due to node allocation and handle dropping; there is no channel perf bench covering this cost. This is a memory-lifetime correction, not a blanket speedup. No fresh GPU, Mac, mini-cluster or ASan run is claimed for this follow-up.