Patchwork D9636: bundle: add option to avoid checking further delta candidates [POC]

login
register
mail settings
Submitter phabricator
Date Dec. 19, 2020, 2:45 p.m.
Message ID <differential-rev-PHID-DREV-eexk7lxrp56ipmw6j5us-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/47946/
State New
Headers show

Comments

phabricator - Dec. 19, 2020, 2:45 p.m.
joerg.sonnenberger created this revision.
Herald added a reviewer: indygreg.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  Especially when applying a clone bundle and the follow-up pull, the
  deltas will be nearly optimal. Add a test config flag to skip any
  attempts at finding a better delta base. Test base for how this
  interacts with parallel delta compression in addgroup.
  
  Test with a bundle of the HG repo: -2%, non-noticable size difference
  Test with a bundle of the NetBSD src repo: -18%, +10% manifest size

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D9636

AFFECTED FILES
  mercurial/changegroup.py
  mercurial/configitems.py
  mercurial/filelog.py
  mercurial/manifest.py
  mercurial/revlog.py
  mercurial/revlogutils/deltas.py
  mercurial/unionrepo.py

CHANGE DETAILS




To: joerg.sonnenberger, indygreg, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/mercurial/unionrepo.py b/mercurial/unionrepo.py
--- a/mercurial/unionrepo.py
+++ b/mercurial/unionrepo.py
@@ -131,6 +131,7 @@ 
         addrevisioncb=None,
         duplicaterevisioncb=None,
         maybemissingparents=False,
+        trustdeltas=False,
     ):
         raise NotImplementedError
 
diff --git a/mercurial/revlogutils/deltas.py b/mercurial/revlogutils/deltas.py
--- a/mercurial/revlogutils/deltas.py
+++ b/mercurial/revlogutils/deltas.py
@@ -1032,7 +1032,7 @@ 
             snapshotdepth,
         )
 
-    def finddeltainfo(self, revinfo, fh):
+    def finddeltainfo(self, revinfo, fh, trustdelta=False):
         """Find an acceptable delta against a candidate revision
 
         revinfo: information about the revision (instance of _revisioninfo)
@@ -1076,8 +1076,12 @@ 
                 if candidatedelta is not None:
                     if isgooddeltainfo(self.revlog, candidatedelta, revinfo):
                         nominateddeltas.append(candidatedelta)
+                        if trustdelta and cachedelta[0] != -1:
+                            break
             if nominateddeltas:
                 deltainfo = min(nominateddeltas, key=lambda x: x.deltalen)
+                if trustdelta and cachedelta[0] != -1:
+                    break
             if deltainfo is not None:
                 candidaterevs = groups.send(deltainfo.base)
             else:
diff --git a/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -2244,6 +2244,7 @@ 
         ifh,
         dfh,
         alwayscache=False,
+        trustdelta=False,
         deltacomputer=None,
     ):
         """internal function to add revisions to the log
@@ -2297,7 +2298,9 @@ 
 
         revinfo = _revisioninfo(node, p1, p2, btext, textlen, cachedelta, flags)
 
-        deltainfo = deltacomputer.finddeltainfo(revinfo, fh)
+        deltainfo = deltacomputer.finddeltainfo(
+            revinfo, fh, trustdelta=trustdelta
+        )
 
         e = (
             offset_type(offset, flags),
@@ -2367,6 +2370,7 @@ 
         transaction,
         addrevisioncb=None,
         duplicaterevisioncb=None,
+        trustdeltas=False,
     ):
         """
         add a delta group
@@ -2467,6 +2471,7 @@ 
                     dfh,
                     alwayscache=bool(addrevisioncb),
                     deltacomputer=deltacomputer,
+                    trustdelta=trustdeltas,
                 )
 
                 if addrevisioncb:
diff --git a/mercurial/manifest.py b/mercurial/manifest.py
--- a/mercurial/manifest.py
+++ b/mercurial/manifest.py
@@ -1838,6 +1838,7 @@ 
         transaction,
         addrevisioncb=None,
         duplicaterevisioncb=None,
+        trustdeltas=False,
     ):
         return self._revlog.addgroup(
             deltas,
@@ -1845,6 +1846,7 @@ 
             transaction,
             addrevisioncb=addrevisioncb,
             duplicaterevisioncb=duplicaterevisioncb,
+            trustdeltas=trustdeltas,
         )
 
     def rawsize(self, rev):
diff --git a/mercurial/filelog.py b/mercurial/filelog.py
--- a/mercurial/filelog.py
+++ b/mercurial/filelog.py
@@ -141,6 +141,7 @@ 
         addrevisioncb=None,
         duplicaterevisioncb=None,
         maybemissingparents=False,
+        trustdeltas=False,
     ):
         if maybemissingparents:
             raise error.Abort(
@@ -156,6 +157,7 @@ 
             transaction,
             addrevisioncb=addrevisioncb,
             duplicaterevisioncb=duplicaterevisioncb,
+            trustdeltas=trustdeltas,
         )
 
     def getstrippoint(self, minlink):
diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -1109,6 +1109,11 @@ 
 )
 coreconfigitem(
     b'experimental',
+    b'trust-bundle-deltas',
+    default=False,
+)
+coreconfigitem(
+    b'experimental',
     b'update.atomic-file',
     default=False,
 )
diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py
--- a/mercurial/changegroup.py
+++ b/mercurial/changegroup.py
@@ -257,7 +257,7 @@ 
         # be empty during the pull
         self.manifestheader()
         deltas = self.deltaiter()
-        repo.manifestlog.getstorage(b'').addgroup(deltas, revmap, trp)
+        repo.manifestlog.getstorage(b'').addgroup(deltas, revmap, trp, trustdeltas=repo.ui.configbool(b'experimental', b'trust-bundle-deltas', False))
         prog.complete()
         self.callback = None
 
@@ -543,7 +543,7 @@ 
             d = chunkdata[b"filename"]
             repo.ui.debug(b"adding %s revisions\n" % d)
             deltas = self.deltaiter()
-            if not repo.manifestlog.getstorage(d).addgroup(deltas, revmap, trp):
+            if not repo.manifestlog.getstorage(d).addgroup(deltas, revmap, trp, trustdeltas=repo.ui.configbool(b'experimental', b'trust-bundle-deltas', False)):
                 raise error.Abort(_(b"received dir revlog group is empty"))
 
 
@@ -1665,6 +1665,7 @@ 
     progress = repo.ui.makeprogress(
         _(b'files'), unit=_(b'files'), total=expectedfiles
     )
+    trustdeltas=repo.ui.configbool(b'experimental', b'trust-bundle-deltas', False)
     for chunkdata in iter(source.filelogheader, {}):
         files += 1
         f = chunkdata[b"filename"]
@@ -1674,7 +1675,7 @@ 
         o = len(fl)
         try:
             deltas = source.deltaiter()
-            if not fl.addgroup(deltas, revmap, trp):
+            if not fl.addgroup(deltas, revmap, trp, trustdeltas=trustdeltas):
                 raise error.Abort(_(b"received file revlog group is empty"))
         except error.CensoredBaseError as e:
             raise error.Abort(_(b"received delta base is censored: %s") % e)