# HG changeset patch # User Durham Goode # Date 1369967343 25200 # Node ID e0aa6fff8f0241a0b655a15a3856b9ddf8bb0cb3 # Parent 93635f69c93b303cad04942bae85e4613005cb0f annotate: simplify annotate parent function The annotate algorithm used a custom parents() function to try to reuse filectx and filelogs. I simplified it a bit to rely more heavily on the self.parents() which makes it work well with alternative filectx implementations. I tested performance on a file with 5000+ revisions but no renames, and on a file with 500 revisions repeating a series of 4 edits+renames and saw zero performance hit. In fact, it was reliably a couple milliseconds faster now. Added the perfannotate command to contrib/perf.py for future use. diff -r 93635f69c93b -r e0aa6fff8f02 contrib/perf.py --- a/contrib/perf.py Thu May 30 19:26:56 2013 -0700 +++ b/contrib/perf.py Thu May 30 19:29:03 2013 -0700 @@ -45,6 +45,11 @@ except Exception: timer(lambda: len(list(cmdutil.walk(repo, pats, {})))) +@command('perfannotate') +def perfannotate(ui, repo, f): + fc = repo['.'][f] + timer(lambda: len(fc.annotate(True))) + @command('perfstatus', [('u', 'unknown', False, 'ask status to look for unknown files')]) diff -r 93635f69c93b -r e0aa6fff8f02 mercurial/context.py --- a/mercurial/context.py Thu May 30 19:26:56 2013 -0700 +++ b/mercurial/context.py Thu May 30 19:29:03 2013 -0700 @@ -649,25 +649,21 @@ return child getlog = util.lrucachefunc(lambda x: self._repo.file(x)) - def getctx(path, fileid): - log = path == self._path and self._filelog or getlog(path) - return filectx(self._repo, path, fileid=fileid, filelog=log) - getctx = util.lrucachefunc(getctx) def parents(f): - # we want to reuse filectx objects as much as possible - p = f._path - if f._filerev is None: # working dir - pl = [(n.path(), n.filerev()) for n in f.parents()] - else: - pl = [(p, n) for n in f._filelog.parentrevs(f._filerev)] + pl = f.parents() + + # Don't return renamed parents if we aren't following. + if not follow: + pl = [p for p in pl if p.path() == f.path()] - if follow: - r = f.renamed() - if r: - pl[0] = (r[0], getlog(r[0]).rev(r[1])) + # renamed filectx won't have a filelog yet, so set it + # from the cache to save time + for p in pl: + if not '_filelog' in p.__dict__: + p._filelog = getlog(p.path()) - return [getctx(p, n) for p, n in pl if n != nullrev] + return pl # use linkrev to find the first changeset where self appeared if self.rev() != self.linkrev():