comparison mercurial/manifest.py @ 29823:27c0792e834c

manifest: break mancache into two caches The old manifest cache cached both the inmemory representation and the raw text. As part of the manifest refactor we want to separate the storage format from the in memory representation, so let's split this cache into two caches. This will let other manifest implementations participate in the in memory cache, while allowing the revlog based implementations to still depend on the full text caching where necessary.
author Durham Goode <durham@fb.com>
date Wed, 17 Aug 2016 13:25:13 -0700
parents 55d341877316
children 58d4ecdc531e
comparison
equal deleted inserted replaced
29822:61a4cdc98307 29823:27c0792e834c
906 if opts is not None: 906 if opts is not None:
907 cachesize = opts.get('manifestcachesize', cachesize) 907 cachesize = opts.get('manifestcachesize', cachesize)
908 usetreemanifest = opts.get('treemanifest', usetreemanifest) 908 usetreemanifest = opts.get('treemanifest', usetreemanifest)
909 usemanifestv2 = opts.get('manifestv2', usemanifestv2) 909 usemanifestv2 = opts.get('manifestv2', usemanifestv2)
910 self._mancache = util.lrucachedict(cachesize) 910 self._mancache = util.lrucachedict(cachesize)
911 self._fulltextcache = util.lrucachedict(cachesize)
911 self._treeinmem = usetreemanifest 912 self._treeinmem = usetreemanifest
912 self._treeondisk = usetreemanifest 913 self._treeondisk = usetreemanifest
913 self._usemanifestv2 = usemanifestv2 914 self._usemanifestv2 = usemanifestv2
914 indexfile = "00manifest.i" 915 indexfile = "00manifest.i"
915 if dir: 916 if dir:
998 999
999 def read(self, node): 1000 def read(self, node):
1000 if node == revlog.nullid: 1001 if node == revlog.nullid:
1001 return self._newmanifest() # don't upset local cache 1002 return self._newmanifest() # don't upset local cache
1002 if node in self._mancache: 1003 if node in self._mancache:
1003 return self._mancache[node][0] 1004 return self._mancache[node]
1004 if self._treeondisk: 1005 if self._treeondisk:
1005 def gettext(): 1006 def gettext():
1006 return self.revision(node) 1007 return self.revision(node)
1007 def readsubtree(dir, subm): 1008 def readsubtree(dir, subm):
1008 return self.dirlog(dir).read(subm) 1009 return self.dirlog(dir).read(subm)
1012 arraytext = None 1013 arraytext = None
1013 else: 1014 else:
1014 text = self.revision(node) 1015 text = self.revision(node)
1015 m = self._newmanifest(text) 1016 m = self._newmanifest(text)
1016 arraytext = array.array('c', text) 1017 arraytext = array.array('c', text)
1017 self._mancache[node] = (m, arraytext) 1018 self._mancache[node] = m
1019 self._fulltextcache[node] = arraytext
1018 return m 1020 return m
1019 1021
1020 def readshallow(self, node): 1022 def readshallow(self, node):
1021 '''Reads the manifest in this directory. When using flat manifests, 1023 '''Reads the manifest in this directory. When using flat manifests,
1022 this manifest will generally have files in subdirectories in it. Does 1024 this manifest will generally have files in subdirectories in it. Does
1032 return m.find(f) 1034 return m.find(f)
1033 except KeyError: 1035 except KeyError:
1034 return None, None 1036 return None, None
1035 1037
1036 def add(self, m, transaction, link, p1, p2, added, removed): 1038 def add(self, m, transaction, link, p1, p2, added, removed):
1037 if (p1 in self._mancache and not self._treeinmem 1039 if (p1 in self._fulltextcache and not self._treeinmem
1038 and not self._usemanifestv2): 1040 and not self._usemanifestv2):
1039 # If our first parent is in the manifest cache, we can 1041 # If our first parent is in the manifest cache, we can
1040 # compute a delta here using properties we know about the 1042 # compute a delta here using properties we know about the
1041 # manifest up-front, which may save time later for the 1043 # manifest up-front, which may save time later for the
1042 # revlog layer. 1044 # revlog layer.
1044 _checkforbidden(added) 1046 _checkforbidden(added)
1045 # combine the changed lists into one sorted iterator 1047 # combine the changed lists into one sorted iterator
1046 work = heapq.merge([(x, False) for x in added], 1048 work = heapq.merge([(x, False) for x in added],
1047 [(x, True) for x in removed]) 1049 [(x, True) for x in removed])
1048 1050
1049 arraytext, deltatext = m.fastdelta(self._mancache[p1][1], work) 1051 arraytext, deltatext = m.fastdelta(self._fulltextcache[p1], work)
1050 cachedelta = self.rev(p1), deltatext 1052 cachedelta = self.rev(p1), deltatext
1051 text = util.buffer(arraytext) 1053 text = util.buffer(arraytext)
1052 n = self.addrevision(text, transaction, link, p1, p2, cachedelta) 1054 n = self.addrevision(text, transaction, link, p1, p2, cachedelta)
1053 else: 1055 else:
1054 # The first parent manifest isn't already loaded, so we'll 1056 # The first parent manifest isn't already loaded, so we'll
1063 else: 1065 else:
1064 text = m.text(self._usemanifestv2) 1066 text = m.text(self._usemanifestv2)
1065 n = self.addrevision(text, transaction, link, p1, p2) 1067 n = self.addrevision(text, transaction, link, p1, p2)
1066 arraytext = array.array('c', text) 1068 arraytext = array.array('c', text)
1067 1069
1068 self._mancache[n] = (m, arraytext) 1070 self._mancache[n] = m
1071 self._fulltextcache[n] = arraytext
1069 1072
1070 return n 1073 return n
1071 1074
1072 def _addtree(self, m, transaction, link, m1, m2): 1075 def _addtree(self, m, transaction, link, m1, m2):
1073 # If the manifest is unchanged compared to one parent, 1076 # If the manifest is unchanged compared to one parent,
1090 m.setnode(n) 1093 m.setnode(n)
1091 return n 1094 return n
1092 1095
1093 def clearcaches(self): 1096 def clearcaches(self):
1094 super(manifest, self).clearcaches() 1097 super(manifest, self).clearcaches()
1098 self._fulltextcache.clear()
1095 self._mancache.clear() 1099 self._mancache.clear()
1096 self._dirlogcache = {'': self} 1100 self._dirlogcache = {'': self}