[PATCH 1 of 2] repoview: invalidate visible cached revs when dynamic blockers change

Laurent Charignon lcharignon at fb.com
Tue Jun 16 12:03:23 CDT 2015

# HG changeset patch
# User Laurent Charignon <lcharignon at fb.com>
# Date 1434407619 25200
#      Mon Jun 15 15:33:39 2015 -0700
# Node ID ec65a79467e52a695700f7abfa9e4c55f3cc6c91
# Parent  a69983942fb4dbfdf5ca8c7a123120ed09ead5db
repoview: invalidate visible cached revs when dynamic blockers change

Before this patch, we were invalidating the filteredrevs cache when the
dynamic blockers changed at each dynamic blocker change.
This patch moves the cache invalidation logic to a central place, when the list
of filteredrevs is queried.

It enhances the performance and legibility of the code:
  - Performance, because we invalidate the cache only when we need the
    result of the computation and only once for multiple changes affecting the
    dynamic blockers.
  - Legibility of the code as we now have a single place to invalidate the cache
    removing the need to invalidate the cache for every operation that could
    make dirty.

diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -322,6 +322,10 @@ class localrepository(object):
         # - bookmark changes
         self.filteredrevcache = {}
+        # holds the dyanmic blockers for the computation of visible revisions,
+        # it is used to know if the filteredrevcache entry for visible is dirty
+        self.cacheddynamicblockers = set()
         # generic mapping between names and nodes
         self.names = namespaces.namespaces()
diff --git a/mercurial/repoview.py b/mercurial/repoview.py
--- a/mercurial/repoview.py
+++ b/mercurial/repoview.py
@@ -240,9 +240,17 @@ filtertable = {'visible': computehidden,
 def filterrevs(repo, filtername):
     """returns set of filtered revision for this filter name"""
+    # Invalidate the cache entry for visible if the dynamic blockers change
+    if (filtername == 'visible' and 'visible' in repo.filteredrevcache and
+            repo.cacheddynamicblockers != _getdynamicblockers(repo)):
+        del repo.filteredrevcache['visible']
     if filtername not in repo.filteredrevcache:
         func = filtertable[filtername]
         repo.filteredrevcache[filtername] = func(repo.unfiltered())
+        if filtername == 'visible':
+            repo.cacheddynamicblockers = _getdynamicblockers(repo)
     return repo.filteredrevcache[filtername]
 class repoview(object):

More information about the Mercurial-devel mailing list