Patchwork [3,of,6,V5] manifest: change manifestlog mancache to be directory based

login
register
mail settings
Submitter Durham Goode
Date Nov. 3, 2016, 1:29 a.m.
Message ID <9034cbde98311be9a93d.1478136598@dev111.prn1.facebook.com>
Download mbox | patch
Permalink /patch/17309/
State Accepted
Headers show

Comments

Durham Goode - Nov. 3, 2016, 1:29 a.m.
# HG changeset patch
# User Durham Goode <durham@fb.com>
# Date 1478131847 25200
#      Wed Nov 02 17:10:47 2016 -0700
# Branch stable
# Node ID 9034cbde98311be9a93da0554a3ca9d399d64089
# Parent  03f320268065807ad4fd90dbfb9b05d5493c250c
manifest: change manifestlog mancache to be directory based

In the last patch we added a get() function that allows fetching directory level
treemanifestctxs. It didn't handle caching at directory level though, so we need to
change our mancache to support multiple directories.

Patch

diff --git a/mercurial/manifest.py b/mercurial/manifest.py
--- a/mercurial/manifest.py
+++ b/mercurial/manifest.py
@@ -1257,9 +1257,17 @@  class manifestlog(object):
         self._oldmanifest = repo._constructmanifest()
         self._revlog = self._oldmanifest
 
+        # A cache of the manifestctx or treemanifestctx for each directory
+        self._dirmancache = {}
+
         # We'll separate this into it's own cache once oldmanifest is no longer
         # used
         self._mancache = self._oldmanifest._mancache
+        self._dirmancache[''] = self._mancache
+
+        # A future patch makes this use the same config value as the existing
+        # mancache
+        self.cachesize = 4
 
     def __getitem__(self, node):
         """Retrieves the manifest instance for the given node. Throws a
@@ -1271,6 +1279,14 @@  class manifestlog(object):
         """Retrieves the manifest instance for the given node. Throws a
         LookupError if not found.
         """
+        if node in self._dirmancache.get(dir, ()):
+            cachemf = self._dirmancache[dir][node]
+            # The old manifest may put non-ctx manifests in the cache, so
+            # skip those since they don't implement the full api.
+            if (isinstance(cachemf, manifestctx) or
+                isinstance(cachemf, treemanifestctx)):
+                return cachemf
+
         if dir:
             if self._revlog._treeondisk:
                 dirlog = self._revlog.dirlog(dir)
@@ -1283,14 +1299,6 @@  class manifestlog(object):
                         _("cannot ask for manifest directory '%s' in a flat "
                           "manifest") % dir)
         else:
-            if node in self._mancache:
-                cachemf = self._mancache[node]
-                # The old manifest may put non-ctx manifests in the cache, so
-                # skip those since they don't implement the full api.
-                if (isinstance(cachemf, manifestctx) or
-                    isinstance(cachemf, treemanifestctx)):
-                    return cachemf
-
             if node not in self._revlog.nodemap:
                 raise LookupError(node, self._revlog.indexfile,
                                   _('no node'))
@@ -1298,8 +1306,13 @@  class manifestlog(object):
                 m = treemanifestctx(self._repo, '', node)
             else:
                 m = manifestctx(self._repo, node)
-            if node != revlog.nullid:
-                self._mancache[node] = m
+
+        if node != revlog.nullid:
+            mancache = self._dirmancache.get(dir)
+            if not mancache:
+                mancache = util.lrucachedict(self.cachesize)
+                self._dirmancache[dir] = mancache
+            mancache[node] = m
         return m
 
     def add(self, m, transaction, link, p1, p2, added, removed):