comparison mercurial/changegroup.py @ 30211:6b0741d6d234

changegroup: skip delta when the underlying revlog do not use them Revlog can now be configured to store full snapshot only. This is used on the changelog. However, the changegroup packing was still recomputing deltas to be sent over the wire. We now just reuse the full snapshot directly in this case, skipping delta computation. This provides use with a large speed up(-30%): # perfchangegroupchangelog on mercurial ! wall 2.010326 comb 2.020000 user 2.000000 sys 0.020000 (best of 5) ! wall 1.382039 comb 1.380000 user 1.370000 sys 0.010000 (best of 8) # perfchangegroupchangelog on pypy ! wall 5.792589 comb 5.780000 user 5.780000 sys 0.000000 (best of 3) ! wall 3.911158 comb 3.920000 user 3.900000 sys 0.020000 (best of 3) # perfchangegroupchangelog on mozilla central ! wall 20.683727 comb 20.680000 user 20.630000 sys 0.050000 (best of 3) ! wall 14.190204 comb 14.190000 user 14.150000 sys 0.040000 (best of 3) Many tests have to be updated because of the change in bundle content. All theses update have been verified. Because diffing changelog was not very valuable, the resulting bundle have similar size (often a bit smaller): # full bundle of mozilla central with delta: 1142740533B without delta: 1142173300B So this is a win all over the board.
author Pierre-Yves David <pierre-yves.david@ens-lyon.org>
date Fri, 14 Oct 2016 01:31:11 +0200
parents edb49a90723c
children 260af19891f2
comparison
equal deleted inserted replaced
30210:5e4f16874a9f 30211:6b0741d6d234
816 # bundle.reorder=auto just like bundle.reorder=False). 816 # bundle.reorder=auto just like bundle.reorder=False).
817 self._reorder = False 817 self._reorder = False
818 818
819 def deltaparent(self, revlog, rev, p1, p2, prev): 819 def deltaparent(self, revlog, rev, p1, p2, prev):
820 dp = revlog.deltaparent(rev) 820 dp = revlog.deltaparent(rev)
821 # Avoid sending full revisions when delta parent is null. Pick 821 if dp == nullrev and revlog.storedeltachains:
822 # prev in that case. It's tempting to pick p1 in this case, as p1 822 # Avoid sending full revisions when delta parent is null. Pick prev
823 # will be smaller in the common case. However, computing a delta 823 # in that case. It's tempting to pick p1 in this case, as p1 will
824 # against p1 may require resolving the raw text of p1, which could 824 # be smaller in the common case. However, computing a delta against
825 # be expensive. The revlog caches should have prev cached, meaning 825 # p1 may require resolving the raw text of p1, which could be
826 # less CPU for changegroup generation. There is likely room to add 826 # expensive. The revlog caches should have prev cached, meaning
827 # a flag and/or config option to control this behavior. 827 # less CPU for changegroup generation. There is likely room to add
828 # 828 # a flag and/or config option to control this behavior.
829 # Pick prev when we can't be sure remote has the base revision.
830 if dp == nullrev or (dp != p1 and dp != p2 and dp != prev):
831 return prev 829 return prev
832 return dp 830 elif dp == nullrev:
831 # revlog is configured to use full snapshot for a reason,
832 # stick to full snapshot.
833 return nullrev
834 elif dp not in (p1, p2, prev):
835 # Pick prev when we can't be sure remote has the base revision.
836 return prev
837 else:
838 return dp
833 839
834 def builddeltaheader(self, node, p1n, p2n, basenode, linknode, flags): 840 def builddeltaheader(self, node, p1n, p2n, basenode, linknode, flags):
835 # Do nothing with flags, it is implicitly 0 in cg1 and cg2 841 # Do nothing with flags, it is implicitly 0 in cg1 and cg2
836 return struct.pack(self.deltaheader, node, p1n, p2n, basenode, linknode) 842 return struct.pack(self.deltaheader, node, p1n, p2n, basenode, linknode)
837 843