Mercurial > hg
changeset 27468:93ac15f03331
revlog: refactor delta chain computation into own function
This code is already written in multiple locations.
While this code needs to be fast and extracting it to its own function
adds overhead, code paths reading delta chains typically read,
decompress, and do binary patching on revlog data from the delta chain.
This other work (especially zlib decompression) almost certainly
accounts for a lot more time than the overhead of introducing a Python
function call. So I'm not worried about the performance impact of this
change.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sun, 20 Dec 2015 18:56:05 -0800 |
parents | fbe292b591ec |
children | 8914296e74a2 |
files | mercurial/revlog.py |
diffstat | 1 files changed, 37 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/revlog.py Sun Dec 20 17:57:44 2015 -0800 +++ b/mercurial/revlog.py Sun Dec 20 18:56:05 2015 -0800 @@ -430,6 +430,41 @@ chaininfocache[rev] = r return r + def _deltachain(self, rev, stoprev=None): + """Obtain the delta chain for a revision. + + ``stoprev`` specifies a revision to stop at. If not specified, we + stop at the base of the chain. + + Returns a 2-tuple of (chain, stopped) where ``chain`` is a list of + revs in ascending order and ``stopped`` is a bool indicating whether + ``stoprev`` was hit. + """ + chain = [] + + # Alias to prevent attribute lookup in tight loop. + index = self.index + generaldelta = self._generaldelta + + iterrev = rev + e = index[iterrev] + while iterrev != e[3] and iterrev != stoprev: + chain.append(iterrev) + if generaldelta: + iterrev = e[3] + else: + iterrev -= 1 + e = index[iterrev] + + if iterrev == stoprev: + stopped = True + else: + chain.append(iterrev) + stopped = False + + chain.reverse() + return chain, stopped + def flags(self, rev): return self.index[rev][0] & 0xFFFF def rawsize(self, rev): @@ -1160,26 +1195,9 @@ raise RevlogError(_('incompatible revision flag %x') % (self.flags(rev) & ~REVIDX_KNOWN_FLAGS)) - # build delta chain - chain = [] - index = self.index # for performance - generaldelta = self._generaldelta - iterrev = rev - e = index[iterrev] - while iterrev != e[3] and iterrev != cachedrev: - chain.append(iterrev) - if generaldelta: - iterrev = e[3] - else: - iterrev -= 1 - e = index[iterrev] - - if iterrev == cachedrev: - # cache hit + chain, stopped = self._deltachain(rev, stoprev=cachedrev) + if stopped: text = self._cache[2] - else: - chain.append(iterrev) - chain.reverse() # drop cache to save memory self._cache = None