# HG changeset patch # User Gregory Szorc # Date 1510638515 28800 # Node ID 1fb0846ad792ff28983ebbdd2f05c0c6e5787a4e # Parent 589eed45a452ddec75abc1307c8897b453b74aa0 bundle2: inline changegroup.readexactly() Profiling reveals this loop is pretty tight. Literally any function call elimination can make a big difference. This commit inlines the relatively trivial changegroup.readexactly() method inside the loop. The results with `hg perfbundleread` on a bundle of the Firefox repo speak for themselves: ! read(8k) ! wall 0.679730 comb 0.680000 user 0.140000 sys 0.540000 (best of 15) ! read(16k) ! wall 0.577228 comb 0.570000 user 0.080000 sys 0.490000 (best of 17) ! read(32k) ! wall 0.516060 comb 0.520000 user 0.040000 sys 0.480000 (best of 20) ! read(128k) ! wall 0.496378 comb 0.490000 user 0.010000 sys 0.480000 (best of 20) ! bundle2 iterparts() ! wall 3.460903 comb 3.460000 user 2.760000 sys 0.700000 (best of 3) ! wall 3.056811 comb 3.050000 user 2.340000 sys 0.710000 (best of 4) ! bundle2 iterparts() seekable ! wall 4.312722 comb 4.310000 user 3.480000 sys 0.830000 (best of 3) ! wall 4.007676 comb 4.000000 user 3.170000 sys 0.830000 (best of 3) ! bundle2 part seek() ! wall 6.754764 comb 6.740000 user 3.970000 sys 2.770000 (best of 3) ! wall 6.267110 comb 6.250000 user 3.480000 sys 2.770000 (best of 3) ! bundle2 part read(8k) ! wall 3.668004 comb 3.660000 user 2.960000 sys 0.700000 (best of 3) ! wall 3.404164 comb 3.400000 user 2.650000 sys 0.750000 (best of 3) ! bundle2 part read(16k) ! wall 3.489196 comb 3.480000 user 2.750000 sys 0.730000 (best of 3) ! wall 3.197972 comb 3.200000 user 2.490000 sys 0.710000 (best of 4) ! bundle2 part read(32k) ! wall 3.388569 comb 3.380000 user 2.640000 sys 0.740000 (best of 3) ! wall 3.060557 comb 3.060000 user 2.340000 sys 0.720000 (best of 4) ! bundle2 part read(128k) ! wall 3.276415 comb 3.270000 user 2.560000 sys 0.710000 (best of 4) ! wall 2.952209 comb 2.950000 user 2.230000 sys 0.720000 (best of 4) Differential Revision: https://phab.mercurial-scm.org/D1392 diff -r 589eed45a452 -r 1fb0846ad792 mercurial/bundle2.py --- a/mercurial/bundle2.py Mon Nov 13 22:05:54 2017 -0800 +++ b/mercurial/bundle2.py Mon Nov 13 21:48:35 2017 -0800 @@ -1198,13 +1198,21 @@ headersize = struct.calcsize(_fpayloadsize) readexactly = changegroup.readexactly + read = fh.read chunksize = _unpack(_fpayloadsize, readexactly(fh, headersize))[0] indebug(ui, 'payload chunk size: %i' % chunksize) + # changegroup.readexactly() is inlined below for performance. while chunksize: if chunksize >= 0: - yield readexactly(fh, chunksize) + s = read(chunksize) + if len(s) < chunksize: + raise error.Abort(_('stream ended unexpectedly ' + ' (got %d bytes, expected %d)') % + (len(s), chunksize)) + + yield s elif chunksize == flaginterrupt: # Interrupt "signal" detected. The regular stream is interrupted # and a bundle2 part follows. Consume it. @@ -1213,7 +1221,13 @@ raise error.BundleValueError( 'negative payload chunk size: %s' % chunksize) - chunksize = _unpack(_fpayloadsize, readexactly(fh, headersize))[0] + s = read(headersize) + if len(s) < headersize: + raise error.Abort(_('stream ended unexpectedly ' + ' (got %d bytes, expected %d)') % + (len(s), chunksize)) + + chunksize = _unpack(_fpayloadsize, s)[0] # indebug() inlined for performance. if dolog: