perf(std): answer List.update through the element's address in ArrayList and TrieList #215
Loading…
Reference in a new issue
No description provided.
Delete branch "loop/207-list-update"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Part of #207
Commit 1 of the two-commit seed rule for #207:
List.updateanswered through the element's address byArrayListandTrieList, so a trait-typed list (aListin a field) changes an element in place through its witness table instead of the default's at/change/set round trip.What changed
std/collections/src/list.trb:ArrayList.updateandTrieList.update, eachvar fn update(index, change) { change self[index] }. The body is the same line as the trait default; it compiles differently becauseselfis anArrayList: the element peephole of finding 3 (compiler/src/ir/elements.trb) turns the round trip intomakeUnique self+callClosure change(&self[index] borrowed). The element is never read out, never has a second owner and is never copied. The trait default stays the round trip (still whatRingListand other implementations get) and its documentation now says so, with a# Panicssection.docs/PERFORMANCE.md: new 9.10 with the change, the numbers and the new instance counts; the 9.6 paragraph marks the member done and the lowering as next.Decisions
ArrayList.update. The element step already exists in both back ends and gives exactly that, so the member is plain TorbScript. That means commit 1 adds no native, syntax, driver flag or string-looked-up name, and this PR does not need a seed refresh (CLAUDE.md, "Seed and breaking changes"). "The VM member" is the same TorbScript member, which the VM interprets from the same IR.TrieListhas theList(...)representation and the same witness table asArrayList, so itsupdatelowers to the sameArrayList_updateinstance. Its own member is still declared so the API and documentation match.devirtualizeProgram. Written at lowering time, it would turn the containers that devirtualization unboxes into closures and undo finding 3. So it is an IR pass after devirtualization, a change of its own (Follow-ups). It also needs no native and no seed.e83c2f3).Measurement
Forge CI (throwaway workflow on this branch, since dropped), the
mainbinary (6374a3f0) and this one (ab43335e, before the rebase) alternating, mean processor time of 3 runs:torb check tests/conformance/adts.trbtorb build --emit-c tests/conformance/adts.trbtorb build --emit-c ./compilerWithin noise. The C emitted for
adts.trbis byte-identical, and the compiler itself never callsupdate. The benefit is in programs that change elements through aListthat cannot be unboxed. Recorded in PERFORMANCE 9.10.Tests
std/collections/tests/list-update.test.trb: ArrayList and TrieList change only the named element; a list in a field with counted elements (record with a string, list of lists); a copy taken before the change still reads the old value; the index is evaluated before the change and the change runs once;RingListkeeps the default.tests/conformance/list-update.trb: a boxedListin a record field (ArrayListmember through the witness table) and a boxedRingList(default), counted elements, evaluation order, copy-on-write; the leak gate applies.tests/conformance/list-update-panic.trb: an out-of-rangeupdatepanics with the message ofArrayList.at(index 2 is out of bounds for a length of 2) at the line of the call, after the preceding lines ran and before the change ran. Exit 101.compiler/tests/elements.test.trb: the uniqueness check.change rows[0]on anArrayListlowers tomakeUnique %0+callClosure %1(&%0[%2] borrowed), with noat, nosetand no copy.Locally (VM): the std test 6/6, both conformance programs match their expectations, elements.test.trb 5/5,
torb format --checkandtorb lintclean on the touched files,torb docs skill docs skills --checkup to date. The native build of the conformance programs is checked by this PR's CI only.Follow-ups
a.list[i].field = v,a.list[i][j] = v) asa.list.update(i) { element => element.field = v }. Keys and value are evaluated before the call (BACKEND 2.3), and the closure is the rest of the path. No seed refresh needed.updateon its own trait-typed fields right away. There is no second commit to migrate.Instance-count tripwires
ArrayList.update/TrieList.updateoverrideList.update, so it becomes a witness-table slot of every list inlower.test.trb/ownership.test.trb's real-code programs: declarations 43 -> 45 (both files), functions 93 -> 97 inlower.test.trb(20 tables, 2 elements unchanged). Second commit; comment history extended, numbers in PERFORMANCE 9.10. The 45 was measured by a probe in CI on the old base; main's count did not move with the rebase (its CI is green at 43), the 97 is derived and checked by this head's CI.CI red on
2dc026c:ci / tier A (linux-x64)(andci / gates, which depends on it) -test compiler/tests (native)fails 2 of 2721 tests, both asserting a function count of 43:lower.test.trb:734("every function ofsource.trbanddiagnostic.trbis lowered or blocked by a named construct",found.lowered + found.stubbed == 43) andownership.test.trb:678("real code passes the extended verifier",owned.lowered + owned.stubbed == 43).main(95a363d, also the base of this PR) is green, so the count most likely moved with the newArrayList.update/TrieList.updatemembers; please adjust the expected count or the cause. No review yet; my request stays pending and the next CI run brings me back.Request changes on
2dc026c. The change itself reads correct; CI is red and the PR is not mergeable, which blocks the merge.Checklist
elements.test.trb), but CI is not green, see 1.ArrayList.update/TrieList.updatereuse thechange self[index]body, which the element step lowers tomakeUnique+callClosure ...(&self[index]); panic message and order are covered by the tests.PERFORMANCE.md9.8, the trait default's documentation).Findings
[blocker]Red CI:ci / tier A (linux-x64)(andci / gates) fail intest compiler/tests (native), 2 of 2721 tests.lower.test.trb:734(found.lowered + found.stubbed == 43) andownership.test.trb:678(owned.lowered + owned.stubbed == 43) are the instance-count tripwire. Their comments say a trait default is a table slot only where an implementation of its trait overrides it;ArrayList.updateis now such an override, soList.updateenters the witness tables of the lists the two files build. Please confirm that this is the cause, then raise both expected counts to the new value and extend the comment history in both files in the same style as the earlier entries (the reason is the new override). Please also mention the new count in PERFORMANCE 9.8, because the PR body says the emitted C ofadts.trbis unchanged, which does not cover these two files.[blocker]Not mergeable: Forgejo reportsmergeable: false; the merge base is6374a3f,mainis at95ac043. Rebase onto currentmain(the repo merges by rebase), re-run CI and request review again. A rebase may also move the count in finding 1, so determine the numbers after it.No question for Torben.
2dc026c1f28c5f25e8feCI red on
8c5f25e:ci / tier A (linux-x64)(andci / gates) -test compiler/tests (native). The head is the throwaway probe commit (test: probe the instance count), which assertsprobeTotal == -1inlower.test.trbandownership.test.trbon purpose, so the red is expected and not a finding on the change. No review yet; my request stays pending and the next CI run brings me back.Before that run: drop the probe commit and set the two expected counts to the value it printed (
68b0cf8already holds the real edit, keep its comment history and the count in PERFORMANCE 9.8). Also rebase onto currentmain(e83c2f3; the PR is not mergeable at merge base95ac043, and the repo merges by rebase), then determine the counts after the rebase, since it may move them.8c5f25e8fefb36c46516New head
fb36c465: probe commit dropped, rebased onto maine83c2f3(PERFORMANCE section renumbered to 9.10 because main took 9.9). The old68b0cf8only carried the PERFORMANCE text, not the test edits, so this head adds them for real:lower.test.trb43 -> 45 declarations and 93 -> 97 functions,ownership.test.trb43 -> 45, comment history extended in both, counts named in PERFORMANCE 9.10. The probe printed 45 on the old base; the 97 is not measured, this head's CI is its check (a mismatch gets fixed in the next push). Re-requested your review.Approved on
fb36c46. Earlier findings are resolved: the probe commit is gone, the branch is rebased onto currentmain(mergeable), and the two instance-count tripwires carry the new values (lower.test.trb45 declarations / 97 functions,ownership.test.trb45) with comment history. The combined CI status for this head is success, includingtier A (linux-x64)andgates, so the derived 97 holds.Checklist
Listfield,RingListdefault, counted elements, evaluation order, copy-on-write, out-of-range panic), IR test inelements.test.trb.ArrayList.update/TrieList.updatereuse the default body, which lowers tomakeUnique+callClosure ...(&self[index]); panic message and order are covered.# Panics, PERFORMANCE 9.10).Non-blocking: none.