| Age | Commit message (Collapse) | Author | Files | Lines |
|
The figures in the README came from a single render of linux.git's tip,
which is an unusually large merge, and from a box that still had load on
it from the previous benchmark. Re-measured on an idle machine over 60
random commits: 12.6 ms to 2.0 ms rather than 14.83 to 3.13.
Also note that the esi-diff fragment does not change, which is the point
worth knowing: fragments carry no subject line and so never ask for
decorations at all.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
01 stopped add_ref_decoration() inflating every tag object, but left two
odb_read_object_info() calls per ref behind: one to classify the ref
target so lookup_object_by_type() can be called, and one to classify
what the ref peels to. Each is a binary search through the pack index.
On linux.git that index is 389 MB across 11.8 million objects, and a
commit page walks 946 refs, so it paid about 1900 of those searches per
request. Profiling put add_ref_decoration() at 78% of the whole frame
render, with odb_read_object_info() 76% and find_pack_entry() 52%.
Neither lookup is necessary. packed-refs only records a peeled line for
refs that point at a tag object, so peeled_oid being present already
says the type is OBJ_TAG. And the peeled object is only ever used as a
key for the decoration; nothing reads its type, so lookup_unknown_object()
gives the same struct a later lookup_commit() would fill in.
Frame render with cgit's cache off, on an i7-7700:
linux.git 14.83 ms -> 3.13 ms
git.git 6.49 ms -> 2.23 ms
A control run serving the same objects through a repository with one ref
instead of 946 costs 1.7 ms, so this closes most of the remaining gap.
Verified byte-identical: git log --decorate over 20000 linux.git commits
and the whole of git.git, for-each-ref and tag -l with peeled fields,
and 6000 cgit commit and diff pages. git's t4202-log, t3200-branch,
t6300-for-each-ref and t7004-tag pass, 976 tests between them, and
cgit's own suite passes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
02-cgit-output-buffering.patch was cut from a working tree that already
carried the ESI work, so it also contained the enable-esi config hook,
cache_key(), the repolink and cgit_fileurl fragment hunks and the
memrchr fix. That contradicted its README and made it fail to apply on
any tree that already had ESI, which is every tree in this repository.
Regenerate it with only the output buffering change: the html.c buffer
itself and the flushes in cache.c, filter.c, cgit.c and ui-shared.c.
Verified to apply cleanly both to stock cgit and on top of the ESI
commits here.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
Two independent performance patches found while measuring the ESI split,
both of which help whether or not a cache sits in front of cgit.
01-git-peel-decoration.patch applies to the git submodule. git's
add_ref_decoration() calls parse_object() on every annotated tag to
follow it to its commit, inflating all of them, even though the ref
backend already hands the callback a peeled object id when packed-refs
has one. Using that takes commit and log pages on git.git from about
6 ms to about 2 ms. Output is byte-identical and git's own t4202-log,
t3200-branch and t6300-for-each-ref pass.
02-cgit-output-buffering.patch applies to cgit. html_raw() did one
write(2) per call: a 1.7 MB diff took 99151 writes averaging 18 bytes.
A 64 KB buffer takes that to 27. The buffer has to be flushed wherever
fd 1 is redirected or handed to another writer, which is the cache slot,
exec filters, and the end of the HTTP headers, because git's archive
code writes snapshots and clone data straight to fd 1.
Kept as patches rather than applied because the first belongs upstream
in git, and the second touches enough of cgit's output path to be worth
landing on its own terms.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|