changeset 18101:a464deecc9dd

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.
author Pierre-Yves David <pierre-yves.david@ens-lyon.org>
date Thu, 20 Dec 2012 17:14:07 +0100
parents 3a6ddacb7198
children 3c7b67b76190
files mercurial/localrepo.py mercurial/obsolete.py mercurial/phases.py mercurial/repoview.py
diffstat 4 files changed, 19 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- 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 ""
--- 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()
--- 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.
--- 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