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.
This commit is contained in:
Matt Mackall 2011-01-18 15:55:46 -06:00
parent 3f7ac1d848
commit 275d2d9cb0

View File

@ -176,10 +176,7 @@ class revlogio(object):
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 @@ class revlog(object):
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 @@ class revlog(object):
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 @@ class revlog(object):
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):