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).