# HG changeset patch # User Pierre-Yves David # Date 1356020047 -3600 # Node ID a464deecc9dd32176a1f8faf1cc48236268f3c2a # Parent 3a6ddacb7198c99be9f2c62d2bea09a8eda36758 clfilter: add a cache on repo for set of revision to filter for a given set. Recomputing the filtered revisions at every access to changelog is far too expensive. This changeset introduce a cache for this information. This cache is hold by the repository (unfiltered repository) and invalidated when necessary. This cache is not a protected attribute (leading _) because some logic that invalidate it is not held by the local repo itself. diff -r 3a6ddacb7198 -r a464deecc9dd mercurial/localrepo.py --- a/mercurial/localrepo.py Thu Dec 20 15:32:42 2012 +0100 +++ b/mercurial/localrepo.py Thu Dec 20 17:14:07 2012 +0100 @@ -239,6 +239,15 @@ # Maps a property name to its util.filecacheentry self._filecache = {} + # hold sets of revision to be filtered + # should be cleared when something might have changed the filter value: + # - new changesets, + # - phase change, + # - new obsolescence marker, + # - working directory parent change, + # - bookmark changes + self.filteredrevcache = {} + def close(self): pass @@ -1093,6 +1102,7 @@ self.unfiltered()._branchcache = None # in UTF-8 self.unfiltered()._branchcachetip = None obsolete.clearobscaches(self) + self.filteredrevcache.clear() def invalidatedirstate(self): '''Invalidates the dirstate, causing the next call to dirstate @@ -1858,6 +1868,7 @@ if key.startswith('dump'): data = base85.b85decode(remoteobs[key]) self.obsstore.mergemarkers(tr, data) + self.filteredrevcache.clear() if tr is not None: tr.close() finally: @@ -2470,6 +2481,7 @@ " with %d changes to %d files%s\n") % (changesets, revisions, files, htext)) obsolete.clearobscaches(self) + self.filteredrevcache.clear() if changesets > 0: p = lambda: cl.writepending() and self.root or "" diff -r 3a6ddacb7198 -r a464deecc9dd mercurial/obsolete.py --- a/mercurial/obsolete.py Thu Dec 20 15:32:42 2012 +0100 +++ b/mercurial/obsolete.py Thu Dec 20 17:14:07 2012 +0100 @@ -738,6 +738,7 @@ if nprec in nsucs: raise util.Abort("changeset %s cannot obsolete itself" % prec) repo.obsstore.create(tr, nprec, nsucs, flag, metadata) + repo.filteredrevcache.clear() tr.close() finally: tr.release() diff -r 3a6ddacb7198 -r a464deecc9dd mercurial/phases.py --- a/mercurial/phases.py Thu Dec 20 15:32:42 2012 +0100 +++ b/mercurial/phases.py Thu Dec 20 17:14:07 2012 +0100 @@ -249,6 +249,7 @@ if targetphase != 0: self.retractboundary(repo, targetphase, delroots) obsolete.clearobscaches(repo) + repo.filteredrevcache.clear() def retractboundary(self, repo, targetphase, nodes): # Be careful to preserve shallow-copied values: do not update @@ -267,6 +268,7 @@ currentroots.intersection_update(ctx.node() for ctx in ctxs) self._updateroots(targetphase, currentroots) obsolete.clearobscaches(repo) + repo.filteredrevcache.clear() def advanceboundary(repo, targetphase, nodes): """Add nodes to a phase changing other nodes phases if necessary. diff -r 3a6ddacb7198 -r a464deecc9dd mercurial/repoview.py --- a/mercurial/repoview.py Thu Dec 20 15:32:42 2012 +0100 +++ b/mercurial/repoview.py Thu Dec 20 17:14:07 2012 +0100 @@ -13,7 +13,10 @@ def filteredrevs(repo, filtername): """returns set of filtered revision for this filter name""" - return filtertable[filtername](repo.unfiltered()) + if filtername not in repo.filteredrevcache: + func = filtertable[filtername] + repo.filteredrevcache[filtername] = func(repo.unfiltered()) + return repo.filteredrevcache[filtername] class repoview(object): """Provide a read/write view of a repo through a filtered changelog