Mercurial > public > mercurial-scm > hg
comparison mercurial/revlog.py @ 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 | 072a675c51f2 |
children | fe79f86099ae |
comparison
equal
deleted
inserted
replaced
27467:fbe292b591ec | 27468:93ac15f03331 |
---|---|
427 # work. For cache hits the length is already included. | 427 # work. For cache hits the length is already included. |
428 compresseddeltalen += e[1] | 428 compresseddeltalen += e[1] |
429 r = (clen, compresseddeltalen) | 429 r = (clen, compresseddeltalen) |
430 chaininfocache[rev] = r | 430 chaininfocache[rev] = r |
431 return r | 431 return r |
432 | |
433 def _deltachain(self, rev, stoprev=None): | |
434 """Obtain the delta chain for a revision. | |
435 | |
436 ``stoprev`` specifies a revision to stop at. If not specified, we | |
437 stop at the base of the chain. | |
438 | |
439 Returns a 2-tuple of (chain, stopped) where ``chain`` is a list of | |
440 revs in ascending order and ``stopped`` is a bool indicating whether | |
441 ``stoprev`` was hit. | |
442 """ | |
443 chain = [] | |
444 | |
445 # Alias to prevent attribute lookup in tight loop. | |
446 index = self.index | |
447 generaldelta = self._generaldelta | |
448 | |
449 iterrev = rev | |
450 e = index[iterrev] | |
451 while iterrev != e[3] and iterrev != stoprev: | |
452 chain.append(iterrev) | |
453 if generaldelta: | |
454 iterrev = e[3] | |
455 else: | |
456 iterrev -= 1 | |
457 e = index[iterrev] | |
458 | |
459 if iterrev == stoprev: | |
460 stopped = True | |
461 else: | |
462 chain.append(iterrev) | |
463 stopped = False | |
464 | |
465 chain.reverse() | |
466 return chain, stopped | |
432 | 467 |
433 def flags(self, rev): | 468 def flags(self, rev): |
434 return self.index[rev][0] & 0xFFFF | 469 return self.index[rev][0] & 0xFFFF |
435 def rawsize(self, rev): | 470 def rawsize(self, rev): |
436 """return the length of the uncompressed text for a given revision""" | 471 """return the length of the uncompressed text for a given revision""" |
1158 # check rev flags | 1193 # check rev flags |
1159 if self.flags(rev) & ~REVIDX_KNOWN_FLAGS: | 1194 if self.flags(rev) & ~REVIDX_KNOWN_FLAGS: |
1160 raise RevlogError(_('incompatible revision flag %x') % | 1195 raise RevlogError(_('incompatible revision flag %x') % |
1161 (self.flags(rev) & ~REVIDX_KNOWN_FLAGS)) | 1196 (self.flags(rev) & ~REVIDX_KNOWN_FLAGS)) |
1162 | 1197 |
1163 # build delta chain | 1198 chain, stopped = self._deltachain(rev, stoprev=cachedrev) |
1164 chain = [] | 1199 if stopped: |
1165 index = self.index # for performance | |
1166 generaldelta = self._generaldelta | |
1167 iterrev = rev | |
1168 e = index[iterrev] | |
1169 while iterrev != e[3] and iterrev != cachedrev: | |
1170 chain.append(iterrev) | |
1171 if generaldelta: | |
1172 iterrev = e[3] | |
1173 else: | |
1174 iterrev -= 1 | |
1175 e = index[iterrev] | |
1176 | |
1177 if iterrev == cachedrev: | |
1178 # cache hit | |
1179 text = self._cache[2] | 1200 text = self._cache[2] |
1180 else: | |
1181 chain.append(iterrev) | |
1182 chain.reverse() | |
1183 | 1201 |
1184 # drop cache to save memory | 1202 # drop cache to save memory |
1185 self._cache = None | 1203 self._cache = None |
1186 | 1204 |
1187 bins = self._chunks(chain, df=_df) | 1205 bins = self._chunks(chain, df=_df) |