changeset 49776:511106bcb16c

debug-revlog: details about non-ancestors delta-bases Deltas against a base that is not an ancestor of the revision that owns this delta are notable. For example, they introduce complexity during the bundling process as the base might not exist on the unbundling side. We detect them in `hg debugrevlog` and print information about them.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Mon, 07 Nov 2022 14:38:52 -0500
parents bd3b6f363fb9
children 7aea9babac5d
files mercurial/revlogutils/debug.py tests/test-sparse-revlog.t
diffstat 2 files changed, 45 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/revlogutils/debug.py	Mon Nov 07 14:24:52 2022 -0500
+++ b/mercurial/revlogutils/debug.py	Mon Nov 07 14:38:52 2022 -0500
@@ -302,13 +302,19 @@
     numsemi = 0
     # snapshot count per depth
     numsnapdepth = collections.defaultdict(lambda: 0)
+    # number of snapshots with a non-ancestor delta
+    numsnapdepth_nad = collections.defaultdict(lambda: 0)
     # delta against previous revision
     numprev = 0
+    # delta against prev, where prev is a non-ancestor
+    numprev_nad = 0
     # delta against first or second parent (not prev)
     nump1 = 0
     nump2 = 0
     # delta against neither prev nor parents
     numother = 0
+    # delta against other that is a non-ancestor
+    numother_nad = 0
     # delta against prev that are also first or second parent
     # (details of `numprev`)
     nump1prev = 0
@@ -358,6 +364,9 @@
                 addsize(size, fullsize)
                 addsize(size, snapsizedepth[0])
         else:
+            nad = (
+                delta != p1 and delta != p2 and not r.isancestorrev(delta, rev)
+            )
             chainlengths.append(chainlengths[delta] + 1)
             baseaddr = chainbases[delta]
             revaddr = r.start(rev)
@@ -371,6 +380,8 @@
                 numsemi += 1
                 depth = r.snapshotdepth(rev)
                 numsnapdepth[depth] += 1
+                if nad:
+                    numsnapdepth_nad[depth] += 1
                 addsize(size, snapsizedepth[depth])
             else:
                 addsize(size, deltasize)
@@ -380,12 +391,15 @@
                         nump1prev += 1
                     elif delta == p2:
                         nump2prev += 1
+                    elif nad:
+                        numprev_nad += 1
                 elif delta == p1:
                     nump1 += 1
                 elif delta == p2:
                     nump2 += 1
                 elif delta != nodemod.nullrev:
                     numother += 1
+                    numother_nad += 1
 
         # Obtain data on the raw chunks in the revlog.
         if util.safehasattr(r, '_getsegmentforrevs'):
@@ -410,7 +424,8 @@
             size[0] = 0
 
     numdeltas = numrevs - numfull - numempty - numsemi
-    numoprev = numprev - nump1prev - nump2prev
+    numoprev = numprev - nump1prev - nump2prev - numprev_nad
+    num_other_ancestors = numother - numother_nad
     totalrawsize = datasize[2]
     datasize[2] /= numrevs
     fulltotal = fullsize[2]
@@ -477,10 +492,17 @@
         b'    snapshot  : ' + fmt % pcfmt(numfull + numsemi, numrevs)
     )
     for depth in sorted(numsnapdepth):
-        ui.write(
-            (b'      lvl-%-3d :       ' % depth)
-            + fmt % pcfmt(numsnapdepth[depth], numrevs)
-        )
+        base = b'      lvl-%-3d :       ' % depth
+        count = fmt % pcfmt(numsnapdepth[depth], numrevs)
+        pieces = [base, count]
+        if numsnapdepth_nad[depth]:
+            pieces[-1] = count = count[:-1]  # drop the final '\n'
+            more = b'  non-ancestor-bases: '
+            anc_count = fmt
+            anc_count %= pcfmt(numsnapdepth_nad[depth], numsnapdepth[depth])
+            pieces.append(more)
+            pieces.append(anc_count)
+        ui.write(b''.join(pieces))
     ui.writenoi18n(b'    deltas    : ' + fmt % pcfmt(numdeltas, numrevs))
     ui.writenoi18n(b'revision size : ' + fmt2 % totalsize)
     ui.writenoi18n(
@@ -561,7 +583,10 @@
                 b'    where prev = p2  : ' + fmt2 % pcfmt(nump2prev, numprev)
             )
             ui.writenoi18n(
-                b'    other            : ' + fmt2 % pcfmt(numoprev, numprev)
+                b'    other-ancestor   : ' + fmt2 % pcfmt(numoprev, numprev)
+            )
+            ui.writenoi18n(
+                b'    unrelated        : ' + fmt2 % pcfmt(numoprev, numprev)
             )
         if gdelta:
             ui.writenoi18n(
@@ -571,5 +596,10 @@
                 b'deltas against p2    : ' + fmt % pcfmt(nump2, numdeltas)
             )
             ui.writenoi18n(
-                b'deltas against other : ' + fmt % pcfmt(numother, numdeltas)
+                b'deltas against ancs  : '
+                + fmt % pcfmt(num_other_ancestors, numdeltas)
             )
+            ui.writenoi18n(
+                b'deltas against other : '
+                + fmt % pcfmt(numother_nad, numdeltas)
+            )
--- a/tests/test-sparse-revlog.t	Mon Nov 07 14:24:52 2022 -0500
+++ b/tests/test-sparse-revlog.t	Mon Nov 07 14:38:52 2022 -0500
@@ -105,11 +105,11 @@
                      delta :        0 (100.00%)
       snapshot  :      383 ( 7.66%)
         lvl-0   :              3 ( 0.06%)
-        lvl-1   :             18 ( 0.36%)
-        lvl-2   :             62 ( 1.24%)
-        lvl-3   :            108 ( 2.16%)
-        lvl-4   :            191 ( 3.82%)
-        lvl-5   :              1 ( 0.02%)
+        lvl-1   :             18 ( 0.36%)  non-ancestor-bases:        9 (50.00%)
+        lvl-2   :             62 ( 1.24%)  non-ancestor-bases:       58 (93.55%)
+        lvl-3   :            108 ( 2.16%)  non-ancestor-bases:      108 (100.00%)
+        lvl-4   :            191 ( 3.82%)  non-ancestor-bases:      180 (94.24%)
+        lvl-5   :              1 ( 0.02%)  non-ancestor-bases:        1 (100.00%)
       deltas    :     4618 (92.34%)
   revision size : 58616973
       snapshot  :  9247844 (15.78%)
@@ -144,9 +144,11 @@
   deltas against prev  : 3906 (84.58%)
       where prev = p1  : 3906     (100.00%)
       where prev = p2  :    0     ( 0.00%)
-      other            :    0     ( 0.00%)
+      other-ancestor   :    0     ( 0.00%)
+      unrelated        :    0     ( 0.00%)
   deltas against p1    :  649 (14.05%)
   deltas against p2    :   63 ( 1.36%)
+  deltas against ancs  :    0 ( 0.00%)
   deltas against other :    0 ( 0.00%)