mercurial/revlogutils/deltas.py
changeset 49610 35d4c2124073
parent 49608 78ba41878f2e
child 49611 2afee2176775
equal deleted inserted replaced
49609:9cac281eb9c0 49610:35d4c2124073
   672     good = None
   672     good = None
   673 
   673 
   674     deltas_limit = textlen * LIMIT_DELTA2TEXT
   674     deltas_limit = textlen * LIMIT_DELTA2TEXT
   675 
   675 
   676     tested = {nullrev}
   676     tested = {nullrev}
   677     candidates = _refinedgroups(revlog, p1, p2, cachedelta)
   677     candidates = _refinedgroups(
       
   678         revlog,
       
   679         p1,
       
   680         p2,
       
   681         cachedelta,
       
   682     )
   678     while True:
   683     while True:
   679         temptative = candidates.send(good)
   684         temptative = candidates.send(good)
   680         if temptative is None:
   685         if temptative is None:
   681             break
   686             break
   682         group = []
   687         group = []
   701             if sparse and revlog.rawsize(rev) < (textlen // LIMIT_BASE2TEXT):
   706             if sparse and revlog.rawsize(rev) < (textlen // LIMIT_BASE2TEXT):
   702                 continue
   707                 continue
   703             # no delta for rawtext-changing revs (see "candelta" for why)
   708             # no delta for rawtext-changing revs (see "candelta" for why)
   704             if revlog.flags(rev) & REVIDX_RAWTEXT_CHANGING_FLAGS:
   709             if revlog.flags(rev) & REVIDX_RAWTEXT_CHANGING_FLAGS:
   705                 continue
   710                 continue
       
   711 
   706             # If we reach here, we are about to build and test a delta.
   712             # If we reach here, we are about to build and test a delta.
   707             # The delta building process will compute the chaininfo in all
   713             # The delta building process will compute the chaininfo in all
   708             # case, since that computation is cached, it is fine to access it
   714             # case, since that computation is cached, it is fine to access it
   709             # here too.
   715             # here too.
   710             chainlen, chainsize = revlog._chaininfo(rev)
   716             chainlen, chainsize = revlog._chaininfo(rev)
   766     # (or from the source revlog)
   772     # (or from the source revlog)
   767     #
   773     #
   768     # This logic only applies to general delta repositories and can be disabled
   774     # This logic only applies to general delta repositories and can be disabled
   769     # through configuration. Disabling reuse source delta is useful when
   775     # through configuration. Disabling reuse source delta is useful when
   770     # we want to make sure we recomputed "optimal" deltas.
   776     # we want to make sure we recomputed "optimal" deltas.
       
   777     debug_info = None
   771     if cachedelta and revlog._generaldelta and revlog._lazydeltabase:
   778     if cachedelta and revlog._generaldelta and revlog._lazydeltabase:
   772         # Assume what we received from the server is a good choice
   779         # Assume what we received from the server is a good choice
   773         # build delta will reuse the cache
   780         # build delta will reuse the cache
       
   781         if debug_info is not None:
       
   782             debug_info['cached-delta.tested'] += 1
   774         good = yield (cachedelta[0],)
   783         good = yield (cachedelta[0],)
   775         if good is not None:
   784         if good is not None:
       
   785             if debug_info is not None:
       
   786                 debug_info['cached-delta.accepted'] += 1
   776             yield None
   787             yield None
   777             return
   788             return
       
   789     # XXX cache me higher
   778     snapshots = collections.defaultdict(list)
   790     snapshots = collections.defaultdict(list)
   779     for candidates in _rawgroups(revlog, p1, p2, cachedelta, snapshots):
   791     groups = _rawgroups(
       
   792         revlog,
       
   793         p1,
       
   794         p2,
       
   795         cachedelta,
       
   796         snapshots,
       
   797     )
       
   798     for candidates in groups:
   780         good = yield candidates
   799         good = yield candidates
   781         if good is not None:
   800         if good is not None:
   782             break
   801             break
   783 
   802 
   784     # If sparse revlog is enabled, we can try to refine the available deltas
   803     # If sparse revlog is enabled, we can try to refine the available deltas
   803         while good != previous:
   822         while good != previous:
   804             previous = good
   823             previous = good
   805             children = tuple(sorted(c for c in snapshots[good]))
   824             children = tuple(sorted(c for c in snapshots[good]))
   806             good = yield children
   825             good = yield children
   807 
   826 
   808     # we have found nothing
   827     if debug_info is not None:
       
   828         if good is None:
       
   829             debug_info['no-solution'] += 1
       
   830 
   809     yield None
   831     yield None
   810 
   832 
   811 
   833 
   812 def _rawgroups(revlog, p1, p2, cachedelta, snapshots=None):
   834 def _rawgroups(revlog, p1, p2, cachedelta, snapshots=None):
   813     """Provides group of revision to be tested as delta base
   835     """Provides group of revision to be tested as delta base
   929         # fulltext.
   951         # fulltext.
   930         yield (prev,)
   952         yield (prev,)
   931 
   953 
   932 
   954 
   933 class deltacomputer:
   955 class deltacomputer:
   934     def __init__(self, revlog, write_debug=None, debug_search=False):
   956     def __init__(
       
   957         self,
       
   958         revlog,
       
   959         write_debug=None,
       
   960         debug_search=False,
       
   961         debug_info=None,
       
   962     ):
   935         self.revlog = revlog
   963         self.revlog = revlog
   936         self._write_debug = write_debug
   964         self._write_debug = write_debug
   937         self._debug_search = debug_search
   965         self._debug_search = debug_search
       
   966         self._debug_info = debug_info
   938 
   967 
   939     def buildtext(self, revinfo, fh):
   968     def buildtext(self, revinfo, fh):
   940         """Builds a fulltext version of a revision
   969         """Builds a fulltext version of a revision
   941 
   970 
   942         revinfo: revisioninfo instance that contains all needed info
   971         revinfo: revisioninfo instance that contains all needed info
  1101         # not calling candelta since only one revision needs test, also to
  1130         # not calling candelta since only one revision needs test, also to
  1102         # avoid overhead fetching flags again.
  1131         # avoid overhead fetching flags again.
  1103         if revinfo.flags & REVIDX_RAWTEXT_CHANGING_FLAGS:
  1132         if revinfo.flags & REVIDX_RAWTEXT_CHANGING_FLAGS:
  1104             return self._fullsnapshotinfo(fh, revinfo, target_rev)
  1133             return self._fullsnapshotinfo(fh, revinfo, target_rev)
  1105 
  1134 
  1106         if self._write_debug is not None:
  1135         gather_debug = (
       
  1136             self._write_debug is not None or self._debug_info is not None
       
  1137         )
       
  1138         debug_search = self._write_debug is not None and self._debug_search
       
  1139 
       
  1140         if gather_debug:
  1107             start = util.timer()
  1141             start = util.timer()
  1108 
       
  1109         debug_search = self._write_debug is not None and self._debug_search
       
  1110 
  1142 
  1111         # count the number of different delta we tried (for debug purpose)
  1143         # count the number of different delta we tried (for debug purpose)
  1112         dbg_try_count = 0
  1144         dbg_try_count = 0
  1113         # count the number of "search round" we did. (for debug purpose)
  1145         # count the number of "search round" we did. (for debug purpose)
  1114         dbg_try_rounds = 0
  1146         dbg_try_rounds = 0
  1120         revlog = self.revlog
  1152         revlog = self.revlog
  1121 
  1153 
  1122         deltainfo = None
  1154         deltainfo = None
  1123         p1r, p2r = revlog.rev(p1), revlog.rev(p2)
  1155         p1r, p2r = revlog.rev(p1), revlog.rev(p2)
  1124 
  1156 
  1125         if self._write_debug is not None:
  1157         if gather_debug:
  1126             if p1r != nullrev:
  1158             if p1r != nullrev:
  1127                 p1_chain_len = revlog._chaininfo(p1r)[0]
  1159                 p1_chain_len = revlog._chaininfo(p1r)[0]
  1128             else:
  1160             else:
  1129                 p1_chain_len = -1
  1161                 p1_chain_len = -1
  1130             if p2r != nullrev:
  1162             if p2r != nullrev:
  1248         elif deltainfo.snapshotdepth:  # pytype: disable=attribute-error
  1280         elif deltainfo.snapshotdepth:  # pytype: disable=attribute-error
  1249             dbg_type = b"snapshot"
  1281             dbg_type = b"snapshot"
  1250         else:
  1282         else:
  1251             dbg_type = b"delta"
  1283             dbg_type = b"delta"
  1252 
  1284 
  1253         if self._write_debug is not None:
  1285         if gather_debug:
  1254             end = util.timer()
  1286             end = util.timer()
  1255             assert deltainfo is not None  # please pytype
       
  1256             used_cached = (
  1287             used_cached = (
  1257                 cachedelta is not None
  1288                 cachedelta is not None
  1258                 and dbg_try_rounds == 1
  1289                 and dbg_try_rounds == 1
  1259                 and dbg_try_count == 1
  1290                 and dbg_try_count == 1
  1260                 and deltainfo.base == cachedelta[0]
  1291                 and deltainfo.base == cachedelta[0]
  1261             )
  1292             )
  1262             dbg = {
  1293             dbg = {
  1263                 'duration': end - start,
  1294                 'duration': end - start,
  1264                 'revision': target_rev,
  1295                 'revision': target_rev,
  1265                 'delta-base': deltainfo.base,
  1296                 'delta-base': deltainfo.base,  # pytype: disable=attribute-error
  1266                 'search_round_count': dbg_try_rounds,
  1297                 'search_round_count': dbg_try_rounds,
  1267                 'using-cached-base': used_cached,
  1298                 'using-cached-base': used_cached,
  1268                 'delta_try_count': dbg_try_count,
  1299                 'delta_try_count': dbg_try_count,
  1269                 'type': dbg_type,
  1300                 'type': dbg_type,
  1270                 'p1-chain-len': p1_chain_len,
  1301                 'p1-chain-len': p1_chain_len,
  1292                 target_revlog = b'FILELOG:'
  1323                 target_revlog = b'FILELOG:'
  1293                 if target_key:
  1324                 if target_key:
  1294                     target_revlog += b'%s:' % target_key
  1325                     target_revlog += b'%s:' % target_key
  1295             dbg['target-revlog'] = target_revlog
  1326             dbg['target-revlog'] = target_revlog
  1296 
  1327 
  1297             msg = (
  1328             if self._debug_info is not None:
  1298                 b"DBG-DELTAS:"
  1329                 self._debug_info.append(dbg)
  1299                 b" %-12s"
  1330 
  1300                 b" rev=%d:"
  1331             if self._write_debug is not None:
  1301                 b" delta-base=%d"
  1332                 msg = (
  1302                 b" is-cached=%d"
  1333                     b"DBG-DELTAS:"
  1303                 b" - search-rounds=%d"
  1334                     b" %-12s"
  1304                 b" try-count=%d"
  1335                     b" rev=%d:"
  1305                 b" - delta-type=%-6s"
  1336                     b" delta-base=%d"
  1306                 b" snap-depth=%d"
  1337                     b" is-cached=%d"
  1307                 b" - p1-chain-length=%d"
  1338                     b" - search-rounds=%d"
  1308                 b" p2-chain-length=%d"
  1339                     b" try-count=%d"
  1309                 b" - duration=%f"
  1340                     b" - delta-type=%-6s"
  1310                 b"\n"
  1341                     b" snap-depth=%d"
  1311             )
  1342                     b" - p1-chain-length=%d"
  1312             msg %= (
  1343                     b" p2-chain-length=%d"
  1313                 dbg["target-revlog"],
  1344                     b" - duration=%f"
  1314                 dbg["revision"],
  1345                     b"\n"
  1315                 dbg["delta-base"],
  1346                 )
  1316                 dbg["using-cached-base"],
  1347                 msg %= (
  1317                 dbg["search_round_count"],
  1348                     dbg["target-revlog"],
  1318                 dbg["delta_try_count"],
  1349                     dbg["revision"],
  1319                 dbg["type"],
  1350                     dbg["delta-base"],
  1320                 dbg["snapshot-depth"],
  1351                     dbg["using-cached-base"],
  1321                 dbg["p1-chain-len"],
  1352                     dbg["search_round_count"],
  1322                 dbg["p2-chain-len"],
  1353                     dbg["delta_try_count"],
  1323                 dbg["duration"],
  1354                     dbg["type"],
  1324             )
  1355                     dbg["snapshot-depth"],
  1325             self._write_debug(msg)
  1356                     dbg["p1-chain-len"],
       
  1357                     dbg["p2-chain-len"],
       
  1358                     dbg["duration"],
       
  1359                 )
       
  1360                 self._write_debug(msg)
  1326         return deltainfo
  1361         return deltainfo
  1327 
  1362 
  1328 
  1363 
  1329 def delta_compression(default_compression_header, deltainfo):
  1364 def delta_compression(default_compression_header, deltainfo):
  1330     """return (COMPRESSION_MODE, deltainfo)
  1365     """return (COMPRESSION_MODE, deltainfo)