Repository navigation
Fix graft_child_maps and graft_masked_branches grafting nothing - #182
Conversation
|
Can we get a specialized micro benchmark for them in the progress so we can compare fixes? |
Grafting nothing at a branch must neither create nor destroy a location: an existing branch is emptied and survives as a dangling path, an absent one stays absent, as after graft of an empty source. graft_child_maps' slow path left the old branch in place for an empty map or one without a root value, its fast path grafted an empty node (tripping a debug assertion) and created the focus, and graft_masked_branches created the focus when every masked branch was absent from the source.
348a5dd to
aac0433
Compare
|
Change from master to fix/graft-nothing (worktree: aac0433 + faster graft_child_maps), with the 95% confidence interval in brackets. Positive means slower.
|
Without remove_unset, more than two maps were grafted one branch at a time, each a descend, graft, set or remove value, and ascend. The maps are now gathered into one byte node and merged into the focus the way graft_masked_branches merges a source node, which that merge is factored out for. An absent source node is now an empty byte node on the stack rather than an allocated one.
|
According to claude, the 40% perf loss src_none_masked and src_bare_value is inherent to the fix itself. on master, not doing that work is the bug. |
|
Hmm that's quite a swing for only serving the purpose of giving a faster zipper algebra -- I can't recall how much this specialization saved. Especially keep half empty, I guess. Do we have benchmarks on zipper algebra @marcin-rzeznicki ? |
|
keep_half_empty is slower on small maps but faster on bigger maps (vs master) |
Grafting nothing at a branch must neither create nor destroy a location: an existing branch is emptied and survives as a dangling path, an absent one stays absent, as after graft of an empty source. graft_child_maps' slow path left the old branch in place for an empty map or one without a root value, its fast path grafted an empty node (tripping a debug assertion) and created the focus, and graft_masked_branches created the focus when every masked branch was absent from the source.