Mercurial > public > mercurial-scm > hg
diff mercurial/revlogutils/deltas.py @ 49228:b909dd35d9ab
deltas: add a debug-delta-find command to analyse delta search
See command documentation for details.
For some reason, pytype is confused by our usage of None/deltainfo variable, so
I had to quiet it.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Fri, 20 May 2022 14:27:46 +0200 |
parents | e6b7c6fbeb48 |
children | 78ba41878f2e |
line wrap: on
line diff
--- a/mercurial/revlogutils/deltas.py Thu May 19 23:39:42 2022 +0100 +++ b/mercurial/revlogutils/deltas.py Fri May 20 14:27:46 2022 +0200 @@ -931,9 +931,10 @@ class deltacomputer: - def __init__(self, revlog, write_debug=None): + def __init__(self, revlog, write_debug=None, debug_search=False): self.revlog = revlog self._write_debug = write_debug + self._debug_search = debug_search def buildtext(self, revinfo, fh): """Builds a fulltext version of a revision @@ -980,6 +981,7 @@ def _builddeltainfo(self, revinfo, base, fh): # can we use the cached delta? revlog = self.revlog + debug_search = self._write_debug is not None and self._debug_search chainbase = revlog.chainbase(base) if revlog._generaldelta: deltabase = base @@ -1009,13 +1011,27 @@ delta = revinfo.cachedelta[1] if delta is None: delta = self._builddeltadiff(base, revinfo, fh) + if debug_search: + msg = b"DBG-DELTAS-SEARCH: uncompressed-delta-size=%d\n" + msg %= len(delta) + self._write_debug(msg) # snapshotdept need to be neither None nor 0 level snapshot if revlog.upperboundcomp is not None and snapshotdepth: lowestrealisticdeltalen = len(delta) // revlog.upperboundcomp snapshotlimit = revinfo.textlen >> snapshotdepth + if debug_search: + msg = b"DBG-DELTAS-SEARCH: projected-lower-size=%d\n" + msg %= lowestrealisticdeltalen + self._write_debug(msg) if snapshotlimit < lowestrealisticdeltalen: + if debug_search: + msg = b"DBG-DELTAS-SEARCH: DISCARDED (snapshot limit)\n" + self._write_debug(msg) return None if revlog.length(base) < lowestrealisticdeltalen: + if debug_search: + msg = b"DBG-DELTAS-SEARCH: DISCARDED (prev size)\n" + self._write_debug(msg) return None header, data = revlog.compress(delta) deltalen = len(header) + len(data) @@ -1090,6 +1106,8 @@ if self._write_debug is not None: start = util.timer() + debug_search = self._write_debug is not None and self._debug_search + # count the number of different delta we tried (for debug purpose) dbg_try_count = 0 # count the number of "search round" we did. (for debug purpose) @@ -1113,6 +1131,10 @@ p2_chain_len = revlog._chaininfo(p2r)[0] else: p2_chain_len = -1 + if debug_search: + msg = b"DBG-DELTAS-SEARCH: SEARCH rev=%d\n" + msg %= target_rev + self._write_debug(msg) groups = _candidategroups( self.revlog, revinfo.textlen, p1r, p2r, cachedelta @@ -1120,21 +1142,93 @@ candidaterevs = next(groups) while candidaterevs is not None: dbg_try_rounds += 1 + if debug_search: + prev = None + if deltainfo is not None: + prev = deltainfo.base + + if p1 in candidaterevs or p2 in candidaterevs: + round_type = b"parents" + elif prev is not None and all(c < prev for c in candidaterevs): + round_type = b"refine-down" + elif prev is not None and all(c > prev for c in candidaterevs): + round_type = b"refine-up" + else: + round_type = b"search-down" + msg = b"DBG-DELTAS-SEARCH: ROUND #%d - %d candidates - %s\n" + msg %= (dbg_try_rounds, len(candidaterevs), round_type) + self._write_debug(msg) nominateddeltas = [] if deltainfo is not None: + if debug_search: + msg = ( + b"DBG-DELTAS-SEARCH: CONTENDER: rev=%d - length=%d\n" + ) + msg %= (deltainfo.base, deltainfo.deltalen) + self._write_debug(msg) # if we already found a good delta, # challenge it against refined candidates nominateddeltas.append(deltainfo) for candidaterev in candidaterevs: + if debug_search: + msg = b"DBG-DELTAS-SEARCH: CANDIDATE: rev=%d\n" + msg %= candidaterev + self._write_debug(msg) + candidate_type = None + if candidaterev == p1: + candidate_type = b"p1" + elif candidaterev == p2: + candidate_type = b"p2" + elif self.revlog.issnapshot(candidaterev): + candidate_type = b"snapshot-%d" + candidate_type %= self.revlog.snapshotdepth( + candidaterev + ) + + if candidate_type is not None: + msg = b"DBG-DELTAS-SEARCH: type=%s\n" + msg %= candidate_type + self._write_debug(msg) + msg = b"DBG-DELTAS-SEARCH: size=%d\n" + msg %= self.revlog.length(candidaterev) + self._write_debug(msg) + msg = b"DBG-DELTAS-SEARCH: base=%d\n" + msg %= self.revlog.deltaparent(candidaterev) + self._write_debug(msg) if candidaterev in excluded_bases: + if debug_search: + msg = b"DBG-DELTAS-SEARCH: EXCLUDED\n" + self._write_debug(msg) continue if candidaterev >= target_rev: + if debug_search: + msg = b"DBG-DELTAS-SEARCH: TOO-HIGH\n" + self._write_debug(msg) continue dbg_try_count += 1 + + if debug_search: + delta_start = util.timer() candidatedelta = self._builddeltainfo(revinfo, candidaterev, fh) + if debug_search: + delta_end = util.timer() + msg = b"DBG-DELTAS-SEARCH: delta-search-time=%f\n" + msg %= delta_end - delta_start + self._write_debug(msg) if candidatedelta is not None: if isgooddeltainfo(self.revlog, candidatedelta, revinfo): + if debug_search: + msg = b"DBG-DELTAS-SEARCH: DELTA: length=%d (GOOD)\n" + msg %= candidatedelta.deltalen + self._write_debug(msg) nominateddeltas.append(candidatedelta) + elif debug_search: + msg = b"DBG-DELTAS-SEARCH: DELTA: length=%d (BAD)\n" + msg %= candidatedelta.deltalen + self._write_debug(msg) + elif debug_search: + msg = b"DBG-DELTAS-SEARCH: NO-DELTA\n" + self._write_debug(msg) if nominateddeltas: deltainfo = min(nominateddeltas, key=lambda x: x.deltalen) if deltainfo is not None: @@ -1145,7 +1239,7 @@ if deltainfo is None: dbg_type = b"full" deltainfo = self._fullsnapshotinfo(fh, revinfo, target_rev) - elif deltainfo.snapshotdepth: + elif deltainfo.snapshotdepth: # pytype: disable=attribute-error dbg_type = b"snapshot" else: dbg_type = b"delta" @@ -1161,8 +1255,13 @@ 'p1-chain-len': p1_chain_len, 'p2-chain-len': p2_chain_len, } - if deltainfo.snapshotdepth is not None: - dbg['snapshot-depth'] = deltainfo.snapshotdepth + if ( + deltainfo.snapshotdepth # pytype: disable=attribute-error + is not None + ): + dbg[ + 'snapshot-depth' + ] = deltainfo.snapshotdepth # pytype: disable=attribute-error else: dbg['snapshot-depth'] = 0 target_revlog = b"UNKNOWN"