bundle2: avoid unbound read when seeking
Currently, seekableunbundlepart.seek() will perform a read() during
seek operations. This will allocate a buffer to hold the raw data
over the seek distance. This can lead to very large allocations
and cause performance to suffer.
We change the code to perform read(32768) in a loop to avoid
potentially large allocations.
`hg perfbundleread` on an uncompressed Firefox bundle reveals
a performance impact:
! bundle2 iterparts()
! wall 2.992605 comb 2.990000 user 2.260000 sys 0.730000 (best of 4)
! bundle2 iterparts() seekable
! wall 3.863810 comb 3.860000 user 3.000000 sys 0.860000 (best of 3)
! bundle2 part seek()
! wall 6.213387 comb 6.200000 user 3.350000 sys 2.850000 (best of 3)
! wall 3.820347 comb 3.810000 user 2.980000 sys 0.830000 (best of 3)
Since seekable bundle parts are (only) used by bundlerepo, this /may/
speed up initial loading of bundle-based repos. But any improvement
will likely only be noticed on very large bundles.
Differential Revision: https://phab.mercurial-scm.org/D1394
Source bundle was generated with the following script:
# hg init
# echo a > a
# ln -s a l
# hg ci -Ama -d'0 0'
# mkdir b
# echo a > b/a
# chmod +x b/a
# hg ci -Amb -d'1 0'
$ hg init
$ hg -q pull "$TESTDIR/bundles/test-manifest.hg"
The next call is expected to return nothing:
$ hg manifest
$ hg co
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg manifest
a
b/a
l
$ hg files -vr .
2 a
2 x b/a (glob)
1 l l
$ hg files -r . -X b
a
l
$ hg manifest -v
644 a
755 * b/a
644 @ l
$ hg manifest --debug
b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 644 a
b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 755 * b/a
047b75c6d7a3ef6a2243bd0e99f94f6ea6683597 644 @ l
$ hg manifest -r 0
a
l
$ hg manifest -r 1
a
b/a
l
$ hg manifest -r tip
a
b/a
l
$ hg manifest tip
a
b/a
l
$ hg manifest --all
a
b/a
l
The next two calls are expected to abort:
$ hg manifest -r 2
abort: unknown revision '2'!
[255]
$ hg manifest -r tip tip
abort: please specify just one revision
[255]