Parents and children of check-in [9bcc83b530]
|
2026-08-24
| ||
| 16:41 |
logstore: adopted index entries slice the blob instead of copying it
Adopting a scan index duplicated every entry hash: 255,167 allocations and copies on a 348MB store to answer, typically, one lookup. The hashes are fixed-length slices of a buffer that was being freed at the end of the open, so the store now holds that buffer for its lifetime and the entries point into it. Opening tcl drops 44.0ms -> 37.5ms; smaller stores scale down with the index. openReadOnlyIndexed takes the blob UNCONDITIONALLY -- on success the store frees it in deinit, on every refusal it frees there. The first cut transferred only on success, both call sites looked right, and the second one double-freed inside commit's autosync. No type and no unit test caught it; only e2e did. A conditional transfer makes every call site restate the rule. Ownership is a prefix, not a per-entry flag: adopted entries come first and a tail resume appends owned ones after them, so borrowed_entries is the split point deinit and the batch rollback both read. The unit test pins that the hashes lie INSIDE the held blob, not merely that they compare equal -- equal bytes prove nothing about where they live, and a future dupe would restore the cost with every assertion still green. This is one part of #143. The CRC that issue names as the largest fixed cost measures 5.2ms of the 44ms (1,860 MB/s over the 9.7MB index), so it is not where the time goes and its integrity check should stay. Refs #143 closed check-in: 1234842809 user: dmestas tags: index-borrow-143 | |
| 16:08 | merge merge-dirty-tree: merge into a dirty working tree (#135) check-in: 944ee007fe user: dmestas tags: trunk | |
| 14:47 | merge readpath-141: diff and artifact read through the image path (#141) check-in: 9bcc83b530 user: dmestas tags: trunk | |
| 14:36 |
diff and artifact: read through the image path, not a whole-store derive
Both opened `.full`, so each invocation re-derived the entire repository view before reading anything. The cost tracked the STORE, not the work: a one-line diff on a 302MB store took 0.33s, and cost the same whether the diff was 13 lines or 4126. diff read two file lists -- exactly what ls reads at 0.04s -- and artifact never touched the derived view at all, resolving through logStore alone. diff inherited `.full` by omission: it called Repository.open directly instead of going through main.openRepo, which is where every other read verb chooses a mode. Nothing failed, so nothing caught it. fossil 112MB 0.06s -> 0.01s tk 240MB 0.14s -> 0.03s sqlite 236MB 0.25s -> 0.03s tcl 302MB 0.33s -> 0.04s Output byte-identical on all four. readpath_test pins which verbs take which path, and pins the comment justifying each deliberate `.full` -- timeline reads the merge mark off adjacency, annotate walks ancestry. An unexplained `.full` is indistinguishable from this bug. grep is named there as an open question rather than pinned, since it also wires --no-cache, which has to move with the mode. The OpenOptions comment claimed ls, cat, info, branch and tag were `.full`. All five have been fast_read since #98; reading it was how this stayed hidden. Fixes #141 closed check-in: e845821a65 user: dmestas tags: readpath-141 | |
| 11:27 | merge update-dirty-tree-135: carry uncommitted work across the move (#135) check-in: 5f6402dd84 user: dmestas tags: trunk | |