comparison mercurial/tags.py @ 42237:9f45d3d526f9

hgtagsfnodescache: inherit fnode from parent when possible If a changeset does not update the content of `.hgtags`, it means it will use the same file-node (for `.hgtags`) as its parents. In this case we can directly reuse the parent's file-node. We use this property when updating the `hgtagsfnodescache` taking a faster path if we already have a cached value for the parents of the node we are looking at. Doing so provides a large performance boost when looking at a lot of fnodes, especially on repository with very large manifest: timing for `tagsmod.fnoderevs(ui, repo, repo.changelog.revs())` mercurial: (41907 revisions, 1923 files) before: 6.9 seconds after: 2.7 seconds (-54%) pypy: (96266 revisions, 5198 files) before: 80 seconds after: 20 seconds (-75%) mozilla-central: (463411 revisions, 272080 files) before: 7166.4 seconds after: 47.8 seconds (-99%, x150 speedup) On a copy of mozilla-try with about 35K heads ans 1.7M changesets, this moves the computation from many hours to a couple of minutes, making it more interesting to do a full warm up of this cache before computing tags (from a cold cache). There seems to be other performance low hanging fruits, like avoiding the use of changectx or a more revision centric logic. However, the new code is fast enough for my needs right now.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Mon, 11 Mar 2019 01:10:20 +0100
parents 2930b31383af
children 6770df6e4365
comparison
equal deleted inserted replaced
42236:2930b31383af 42237:9f45d3d526f9
16 16
17 from .node import ( 17 from .node import (
18 bin, 18 bin,
19 hex, 19 hex,
20 nullid, 20 nullid,
21 nullrev,
21 short, 22 short,
22 ) 23 )
23 from .i18n import _ 24 from .i18n import _
24 from . import ( 25 from . import (
25 encoding, 26 encoding,
716 # If we get here, the entry is either missing or invalid. 717 # If we get here, the entry is either missing or invalid.
717 718
718 if not computemissing: 719 if not computemissing:
719 return None 720 return None
720 721
721 # Populate missing entry. 722 fnode = None
722 try: 723 cl = self._repo.changelog
723 fnode = ctx.filenode('.hgtags') 724 p1rev, p2rev = cl._uncheckedparentrevs(rev)
724 except error.LookupError: 725 p1node = cl.node(p1rev)
725 # No .hgtags file on this revision. 726 p1fnode = self.getfnode(p1node, computemissing=False)
726 fnode = nullid 727 if p2rev != nullrev:
728 # There is some no-merge changeset where p1 is null and p2 is set
729 # Processing them as merge is just slower, but still gives a good
730 # result.
731 p2node = cl.node(p1rev)
732 p2fnode = self.getfnode(p2node, computemissing=False)
733 if p1fnode != p2fnode:
734 # we cannot rely on readfast because we don't know against what
735 # parent the readfast delta is computed
736 p1fnode = None
737 if p1fnode is not None:
738 mctx = ctx.manifestctx()
739 fnode = mctx.readfast().get('.hgtags')
740 if fnode is None:
741 fnode = p1fnode
742 if fnode is None:
743 # Populate missing entry.
744 try:
745 fnode = ctx.filenode('.hgtags')
746 except error.LookupError:
747 # No .hgtags file on this revision.
748 fnode = nullid
727 749
728 self._writeentry(offset, properprefix, fnode) 750 self._writeentry(offset, properprefix, fnode)
729 return fnode 751 return fnode
730 752
731 def setfnode(self, node, fnode): 753 def setfnode(self, node, fnode):