Mercurial > hg
comparison mercurial/revlog.py @ 14252:19067884c5f5
revlog: calculate base revisions iteratively
This is in preparation for generaldelta, where the revlog entry base field is
reinterpreted as the deltaparent. For that reason we also rename the base
function to chainbase.
Without generaldelta, performance is unaffected, but generaldelta will suffer
from this in _addrevision, since delta chains will be walked repeatedly.
A cache has been added to eliminate this problem completely.
author | Sune Foldager <cryo@cyanite.org> |
---|---|
date | Sat, 07 May 2011 22:40:14 +0200 |
parents | 258fbccf22f5 |
children | c28d5200374c |
comparison
equal
deleted
inserted
replaced
14251:258fbccf22f5 | 14252:19067884c5f5 |
---|---|
215 """ | 215 """ |
216 self.indexfile = indexfile | 216 self.indexfile = indexfile |
217 self.datafile = indexfile[:-2] + ".d" | 217 self.datafile = indexfile[:-2] + ".d" |
218 self.opener = opener | 218 self.opener = opener |
219 self._cache = None | 219 self._cache = None |
220 self._basecache = None | |
220 self._chunkcache = (0, '') | 221 self._chunkcache = (0, '') |
221 self.index = [] | 222 self.index = [] |
222 self._pcache = {} | 223 self._pcache = {} |
223 self._nodecache = {nullid: nullrev} | 224 self._nodecache = {nullid: nullrev} |
224 self._nodepos = None | 225 self._nodepos = None |
311 return int(self.index[rev][0] >> 16) | 312 return int(self.index[rev][0] >> 16) |
312 def end(self, rev): | 313 def end(self, rev): |
313 return self.start(rev) + self.length(rev) | 314 return self.start(rev) + self.length(rev) |
314 def length(self, rev): | 315 def length(self, rev): |
315 return self.index[rev][1] | 316 return self.index[rev][1] |
316 def base(self, rev): | 317 def chainbase(self, rev): |
317 return self.index[rev][3] | 318 index = self.index |
319 base = index[rev][3] | |
320 while base != rev: | |
321 rev = base | |
322 base = index[rev][3] | |
323 return base | |
318 def flags(self, rev): | 324 def flags(self, rev): |
319 return self.index[rev][0] & 0xFFFF | 325 return self.index[rev][0] & 0xFFFF |
320 def rawsize(self, rev): | 326 def rawsize(self, rev): |
321 """return the length of the uncompressed text for a given revision""" | 327 """return the length of the uncompressed text for a given revision""" |
322 l = self.index[rev][2] | 328 l = self.index[rev][2] |
848 cachedrev = self._cache[1] | 854 cachedrev = self._cache[1] |
849 | 855 |
850 # look up what we need to read | 856 # look up what we need to read |
851 text = None | 857 text = None |
852 rev = self.rev(node) | 858 rev = self.rev(node) |
853 base = self.base(rev) | |
854 | 859 |
855 # check rev flags | 860 # check rev flags |
856 if self.flags(rev) & ~REVIDX_KNOWN_FLAGS: | 861 if self.flags(rev) & ~REVIDX_KNOWN_FLAGS: |
857 raise RevlogError(_('incompatible revision flag %x') % | 862 raise RevlogError(_('incompatible revision flag %x') % |
858 (self.flags(rev) & ~REVIDX_KNOWN_FLAGS)) | 863 (self.flags(rev) & ~REVIDX_KNOWN_FLAGS)) |
859 | 864 |
860 # build delta chain | 865 # build delta chain |
861 chain = [] | 866 chain = [] |
867 index = self.index # for performance | |
862 iterrev = rev | 868 iterrev = rev |
863 while iterrev != base and iterrev != cachedrev: | 869 e = index[iterrev] |
870 while iterrev != e[3] and iterrev != cachedrev: | |
864 chain.append(iterrev) | 871 chain.append(iterrev) |
865 iterrev -= 1 | 872 iterrev -= 1 |
873 e = index[iterrev] | |
866 chain.reverse() | 874 chain.reverse() |
867 base = iterrev | 875 base = iterrev |
868 | 876 |
869 if iterrev == cachedrev: | 877 if iterrev == cachedrev: |
870 # cache hit | 878 # cache hit |
982 t = buildtext() | 990 t = buildtext() |
983 ptext = self.revision(self.node(rev)) | 991 ptext = self.revision(self.node(rev)) |
984 delta = mdiff.textdiff(ptext, t) | 992 delta = mdiff.textdiff(ptext, t) |
985 data = compress(delta) | 993 data = compress(delta) |
986 l = len(data[1]) + len(data[0]) | 994 l = len(data[1]) + len(data[0]) |
987 base = self.base(rev) | 995 basecache = self._basecache |
996 if basecache and basecache[0] == rev: | |
997 base = basecache[1] | |
998 else: | |
999 base = self.chainbase(rev) | |
988 dist = l + offset - self.start(base) | 1000 dist = l + offset - self.start(base) |
989 return dist, l, data, base | 1001 return dist, l, data, base |
990 | 1002 |
991 curr = len(self) | 1003 curr = len(self) |
992 prev = curr - 1 | 1004 prev = curr - 1 |
1036 ifh.write(data[1]) | 1048 ifh.write(data[1]) |
1037 self.checkinlinesize(transaction, ifh) | 1049 self.checkinlinesize(transaction, ifh) |
1038 | 1050 |
1039 if type(text) == str: # only accept immutable objects | 1051 if type(text) == str: # only accept immutable objects |
1040 self._cache = (node, curr, text) | 1052 self._cache = (node, curr, text) |
1053 self._basecache = (curr, base) | |
1041 return node | 1054 return node |
1042 | 1055 |
1043 def group(self, nodelist, bundler): | 1056 def group(self, nodelist, bundler): |
1044 """Calculate a delta group, yielding a sequence of changegroup chunks | 1057 """Calculate a delta group, yielding a sequence of changegroup chunks |
1045 (strings). | 1058 (strings). |