The cold-open issue carried a suspicion: that opening a large repository costs most of a second, that every read verb pays it, and that the cost was allocation and validation after the bytes land, since reading the sidecars took thirty milliseconds. Measured on 0.3.18, the last part was right and the first two were not.
A warm cache hit reads one sidecar, the repository image, and points at it in
place. The only pass over the whole buffer is a checksum. Read verbs that go
through the open funnel get a view in the time that checksum takes, about
sixty milliseconds on the million-artifact pkgsrc mirror. info and
timeline already opened that fast.
zit log reached past the funnel and called the repository open with the
default options. The default mode was the full record replay, the one meant
for write verbs, which rebuilds a mutable state from every record in the
image. For a symbolic name such as trunk, log paid it twice: once to
resolve the name, once to walk. Correct output, no error, and 0.94 seconds
before the first row where the image path gives 0.05.
This is the second time a defaulted field has cost a verb a whole derive.
diff did the same in an earlier release, and the comment above the field
named the trap. Naming a trap does not close it. 0.3.19 opens log once, on
the image, for every route, and removes the default: every caller now says
which mode it wants, so a verb written past the funnel cannot inherit the
expensive one silently. Output is byte-identical on every route, and an
end-to-end test runs each route under the derive-footprint seam and fails if
a record is replayed.
| release build, warm cache | 0.3.18 | 0.3.19 |
|---|---|---|
log -n 1 trunk, SQLite mirror |
0.46s | 0.02s |
log -n 1 trunk, pkgsrc sub-manifest mirror |
0.94s | 0.05s |
log --long -n 5 trunk Makefile, pkgsrc |
1.32s | 0.40s |
What remains on the per-file query is after open: the manifest reads
--long needs for its rows. The sixty-millisecond checksum floor is real,
and nothing asks for less yet.