Commit 7929837
perf(sorted_set): compute union size from split drops instead of recounting
Resolves the TODO in union: after merging, the result size was
recomputed by a full each() traversal of the merged tree. An element
common to both sets is dropped exactly once, at the found pivot of the
split, so union now counts those drops and derives the size
arithmetically: size = |self| + |src| - dups.
Rebased reimplementation: when this PR was first written, union's
`split` was the only splitter and gained an Int drop-count component.
main has since grown `split_member` (the split-based difference/
intersection/symmetric_difference rewrite), whose found flag carries
exactly the same information - so union now uses `split_member`, and
the now-unused `split` is deleted along with its whitebox test, which
is replaced by an equivalent `split_member` test pinning found for
present, absent, below-range, above-range and empty splits.
`split_member`'s result also becomes a `#valtype` struct
(`SplitResult`: left/found/right) instead of a 3-tuple, keeping the
per-node result stack-allocated on native (same pattern as
`JsonNumberScan` in json/lex_number.mbt). This benefits every
split-based operation, not just union.
Benchmarks (moon bench --release, n=10K sets, means of 10x batches):
union, main -> this branch (recount removed + valtype):
50% overlap native 518 -> 429us (-17%), js 297 -> 222us (-25%),
wasm-gc 197 -> 158us (-20%)
disjoint native 382 -> 304us (-20%), js 261 -> 153us (-41%),
wasm-gc 154 -> 96us (-38%)
identical native 592 -> 520us (-12%), js 323 -> 277us (-14%),
wasm-gc 232 -> 193us (-17%)
valtype struct vs tuple (isolated, all split-based ops):
native -5% to -9% across union/difference/intersection;
js flat; wasm-gc within noise (+/-2%).
Tests: union exact-size assertions for overlapping, disjoint and
identical operands cross-checked against an element count; the
split_member whitebox test above; the existing invariant and
quickcheck suites. Mutation-verified: double-counting dups fails 8
tests including the exact-size test and the whitebox invariant
scenarios.
Partially addresses #3824 (the defensive copy_tree of both operands is
inherent to the mutable node design and stays).
Codex CLI review (xhigh, first-round sign-off on the rebased
reimplementation): the dups induction re-verified on split_member
(disjoint fragments, pivot counted exactly once, empty-side arms cannot
hide common elements), sizes read from unmutated copies, SplitResult
preserves tuple semantics at all four call sites, no split callers
remain, interface byte-identical.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Codex CLI <codex@openai.com>1 parent 6da28eb commit 7929837
2 files changed
Lines changed: 68 additions & 65 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
177 | 177 | | |
178 | 178 | | |
179 | 179 | | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
180 | 184 | | |
181 | 185 | | |
182 | 186 | | |
183 | 187 | | |
184 | 188 | | |
185 | | - | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
186 | 193 | | |
187 | 194 | | |
188 | 195 | | |
| |||
191 | 198 | | |
192 | 199 | | |
193 | 200 | | |
194 | | - | |
195 | | - | |
196 | | - | |
197 | | - | |
198 | | - | |
199 | | - | |
200 | | - | |
201 | | - | |
202 | | - | |
| 201 | + | |
| 202 | + | |
203 | 203 | | |
204 | 204 | | |
205 | 205 | | |
| |||
208 | 208 | | |
209 | 209 | | |
210 | 210 | | |
211 | | - | |
212 | | - | |
213 | | - | |
214 | | - | |
215 | | - | |
216 | | - | |
217 | | - | |
218 | | - | |
219 | | - | |
220 | | - | |
221 | | - | |
222 | | - | |
223 | | - | |
224 | | - | |
225 | | - | |
226 | | - | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
227 | 219 | | |
228 | 220 | | |
229 | 221 | | |
230 | | - | |
231 | | - | |
232 | | - | |
233 | | - | |
234 | | - | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
235 | 225 | | |
236 | | - | |
| 226 | + | |
237 | 227 | | |
238 | 228 | | |
239 | 229 | | |
240 | | - | |
| 230 | + | |
241 | 231 | | |
242 | | - | |
243 | | - | |
| 232 | + | |
| 233 | + | |
244 | 234 | | |
245 | | - | |
246 | | - | |
| 235 | + | |
| 236 | + | |
247 | 237 | | |
248 | 238 | | |
249 | 239 | | |
| |||
369 | 359 | | |
370 | 360 | | |
371 | 361 | | |
372 | | - | |
| 362 | + | |
373 | 363 | | |
374 | 364 | | |
375 | 365 | | |
| |||
425 | 415 | | |
426 | 416 | | |
427 | 417 | | |
428 | | - | |
| 418 | + | |
429 | 419 | | |
430 | 420 | | |
431 | 421 | | |
| |||
475 | 465 | | |
476 | 466 | | |
477 | 467 | | |
478 | | - | |
| 468 | + | |
479 | 469 | | |
480 | 470 | | |
481 | 471 | | |
| |||
1038 | 1028 | | |
1039 | 1029 | | |
1040 | 1030 | | |
1041 | | - | |
1042 | | - | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
1043 | 1037 | | |
1044 | 1038 | | |
1045 | | - | |
| 1039 | + | |
| 1040 | + | |
| 1041 | + | |
| 1042 | + | |
| 1043 | + | |
1046 | 1044 | | |
1047 | 1045 | | |
1048 | | - | |
| 1046 | + | |
| 1047 | + | |
| 1048 | + | |
| 1049 | + | |
| 1050 | + | |
1049 | 1051 | | |
1050 | 1052 | | |
1051 | | - | |
| 1053 | + | |
| 1054 | + | |
| 1055 | + | |
| 1056 | + | |
| 1057 | + | |
1052 | 1058 | | |
1053 | 1059 | | |
1054 | | - | |
| 1060 | + | |
| 1061 | + | |
1055 | 1062 | | |
1056 | 1063 | | |
1057 | | - | |
1058 | | - | |
1059 | | - | |
1060 | | - | |
1061 | | - | |
1062 | | - | |
1063 | | - | |
1064 | | - | |
1065 | | - | |
1066 | | - | |
1067 | | - | |
1068 | | - | |
1069 | | - | |
1070 | | - | |
1071 | | - | |
1072 | | - | |
1073 | | - | |
1074 | | - | |
1075 | | - | |
1076 | 1064 | | |
1077 | 1065 | | |
1078 | 1066 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
564 | 564 | | |
565 | 565 | | |
566 | 566 | | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
0 commit comments