hgweb: cache fctx.parents() in annotate command (issue5414)
9c37df347485 introduced a call to fctx.parents() for each line in
annotate output. This function call isn't cheap, as it requires
linkrev adjustment.
Since multiple lines in annotate output tend to belong to the same
file revision, a cache of fctx.parents() lookups for each input
should be effective in the common case. So we implement one.
Since the cache has to precompute parents so an aborted generator
doesn't leave an incomplete cache, we could just return a list.
However, we preserve the generator for backwards compatibility.
The effect of this change when requesting /annotate/96ca0ecdcfa/
browser/locales/en-US/chrome/browser/downloads/downloads.dtd on
the mozilla-aurora repo is significant:
p1(9c37df347485) 5.5s
9c37df347485: 66.3s
this patch: 10.8s
We're still slower than before. But only by ~2x instead of ~12x.
On the tip revisions of layout/base/nsCSSFrameConstructor.cpp file in
the mozilla-unified repo, time went from 12.5s to 14.5s and back to
12.5s. I'm not sure why the mozilla-aurora repo is so slow.
Looking at the code of basefilectx.parents(), there is room for
further improvements. Notably, we still perform redundant calls to
filelog.renamed() and basefilectx._parentfilectx(). And
basefilectx.annotate() also makes similar calls, so there is potential
for object reuse. However, introducing caches here are not appropriate
for the stable branch.
https://bz.mercurial-scm.org/2137
Setup:
create a little extension that has 3 side-effects:
1) ensure changelog data is not inlined
2) make revlog to use lazyparser
3) test that repo.lookup() works
1 and 2 are preconditions for the bug; 3 is the bug.
$ cat > commitwrapper.py <<EOF
> from mercurial import extensions, node, revlog
>
> def reposetup(ui, repo):
> class wraprepo(repo.__class__):
> def commit(self, *args, **kwargs):
> result = super(wraprepo, self).commit(*args, **kwargs)
> tip1 = node.short(repo.changelog.tip())
> tip2 = node.short(repo.lookup(tip1))
> assert tip1 == tip2
> ui.write('new tip: %s\n' % tip1)
> return result
> repo.__class__ = wraprepo
>
> def extsetup(ui):
> revlog._maxinline = 8 # split out 00changelog.d early
> revlog._prereadsize = 8 # use revlog.lazyparser
> EOF
$ cat >> $HGRCPATH <<EOF
> [extensions]
> commitwrapper = `pwd`/commitwrapper.py
> EOF
$ hg init repo1
$ cd repo1
$ echo a > a
$ hg commit -A -m'add a with a long commit message to make the changelog a bit bigger'
adding a
new tip: 553596fad57b
Test that new changesets are visible to repo.lookup():
$ echo a >> a
$ hg commit -m'one more commit to demonstrate the bug'
new tip: 799ae3599e0e
$ hg tip
changeset: 1:799ae3599e0e
tag: tip
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: one more commit to demonstrate the bug
$ cd ..