mercurial/revlogutils/deltas.py
changeset 49249 b909dd35d9ab
parent 49247 e6b7c6fbeb48
child 49737 78ba41878f2e
--- 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"