# HG changeset patch # User Matt Mackall # Date 1295387746 21600 # Node ID 68da048b4c886ac91abd8f1ab30e5c2846bfcde1 # Parent 57d433f632b7f76dea25cd38d0a8f4028d4dd1b8 revlog: incrementally build node cache with linear searches This avoids needing to prime the cache for operations like verify which visit most or all of the index. diff -r 57d433f632b7 -r 68da048b4c88 mercurial/revlog.py --- a/mercurial/revlog.py Fri Jan 07 10:48:30 2011 +0100 +++ b/mercurial/revlog.py Tue Jan 18 15:55:46 2011 -0600 @@ -176,10 +176,7 @@ def parseindex(self, data, inline): # call the C implementation to parse the index data index, cache = parsers.parse_index2(data, inline) - nodemap = None - if not data: - nodemap = {nullid: nullrev} - return index, nodemap, cache + return index, None, cache def packentry(self, entry, node, version, rev): p = _pack(indexformatng, *entry) @@ -228,6 +225,8 @@ self._shallowroot = shallowroot self._parentdelta = 0 self._pcache = {} + self._nodecache = {nullid: nullrev} + self._nodepos = None v = REVLOG_DEFAULT_VERSION if hasattr(opener, 'options') and 'defversion' in opener.options: @@ -274,20 +273,10 @@ raise RevlogError(_("index %s is corrupted") % (self.indexfile)) self.index, nodemap, self._chunkcache = d if nodemap is not None: - self.nodemap = nodemap - self.rev = self._revmap + self.nodemap = self._nodecache = nodemap if not self._chunkcache: self._chunkclear() - @util.propertycache - def nodemap(self): - n = {nullid: nullrev} - i = self.index - for r in xrange(len(i) - 1): - n[i[r][7]] = r - self.rev = self._revmap - return n - def tip(self): return self.node(len(self.index) - 2) def __len__(self): @@ -295,20 +284,31 @@ def __iter__(self): for i in xrange(len(self)): yield i - def _revmap(self, node): - try: - return self.nodemap[node] - except KeyError: - raise LookupError(node, self.indexfile, _('no node')) + + @util.propertycache + def nodemap(self): + n = self.rev(self.node(0)) + return self._nodecache def rev(self, node): - if node == nullid: - return nullrev - i = self.index - for r in xrange(len(i) - 2, -1, -1): - if i[r][7] == node: - return r - raise LookupError(node, self.indexfile, _('no node')) + try: + return self._nodecache[node] + except KeyError: + n = self._nodecache + if node in n: + return n[node] + i = self.index + p = self._nodepos + if p is None: + p = len(i) - 2 + for r in xrange(p, -1, -1): + v = i[r][7] + n[v] = r + if v == node: + self._nodepos = r - 1 + return r + raise LookupError(node, self.indexfile, _('no node')) + def node(self, rev): return self.index[rev][7] def linkrev(self, rev):