status: prefer relative paths in Rust code
… when the repository root is under the current directory,
so the kernel needs to traverse fewer directory in every call
to `read_dir` or `symlink_metadata`.
Better yet would be to use libc functions like `openat` and `fstatat`
to remove such repeated traversals entirely, but the standard library
does not provide APIs based on those.
Maybe with a crate like https://crates.io/crates/openat instead?
Benchmarks of `rhg status` show that this patch is neutral in some configurations,
and makes the command up to ~20% faster in others.
Below is semi-arbitrary subset of results. The four numeric columns are:
time (in seconds) with this changeset’s parent, time with this changeset,
time difference (negative is better), time ratio (less than 1 is better).
```
mercurial-dirstate-v1 | default-plain-clean.no-iu.pbr | 0.0061 -> 0.0059: -0.0002 (0.97)
mercurial-dirstate-v2 | default-plain-clean.no-iu.pbr | 0.0029 -> 0.0028: -0.0001 (0.97)
mozilla-dirstate-v1 | default-plain-clean.no-iu.pbr | 0.2110 -> 0.2102: -0.0007 (1.00)
mozilla-dirstate-v2 | default-copies-clean.ignored.pbr | 0.0489 -> 0.0401: -0.0088 (0.82)
mozilla-dirstate-v2 | default-copies-clean.no-iu.pbr | 0.0479 -> 0.0393: -0.0085 (0.82)
mozilla-dirstate-v2 | default-copies-large.all.pbr | 0.1262 -> 0.1210: -0.0051 (0.96)
mozilla-dirstate-v2 | default-copies-small.ignored-unknown.pbr | 0.1262 -> 0.1200: -0.0062 (0.95)
mozilla-dirstate-v2 | default-copies-small.ignored.pbr | 0.0536 -> 0.0417: -0.0119 (0.78)
mozilla-dirstate-v2 | default-copies-small.no-iu.pbr | 0.0482 -> 0.0393: -0.0089 (0.81)
mozilla-dirstate-v2 | default-plain-clean.ignored.pbr | 0.0518 -> 0.0402: -0.0116 (0.78)
mozilla-dirstate-v2 | default-plain-clean.no-iu.pbr | 0.0481 -> 0.0392: -0.0088 (0.82)
mozilla-dirstate-v2 | default-plain-large.all.pbr | 0.1271 -> 0.1218: -0.0052 (0.96)
mozilla-dirstate-v2 | default-plain-small.ignored-unknown.pbr | 0.1225 -> 0.1202: -0.0022 (0.98)
mozilla-dirstate-v2 | default-plain-small.ignored.pbr | 0.0510 -> 0.0418: -0.0092 (0.82)
mozilla-dirstate-v2 | default-plain-small.no-iu.pbr | 0.0480 -> 0.0394: -0.0086 (0.82)
netbeans-dirstate-v1 | default-plain-clean.no-iu.pbr | 0.1442 -> 0.1422: -0.0020 (0.99)
netbeans-dirstate-v2 | default-plain-clean.no-iu.pbr | 0.0325 -> 0.0282: -0.0043 (0.87)
```
Differential Revision: https://phab.mercurial-scm.org/D12175
#require no-reposimplestore
Test creating a consuming stream bundle v2
$ getmainid() {
> hg -R main log --template '{node}\n' --rev "$1"
> }
$ cp $HGRCPATH $TESTTMP/hgrc.orig
$ cat >> $HGRCPATH << EOF
> [experimental]
> evolution.createmarkers=True
> evolution.exchange=True
> bundle2-output-capture=True
> [ui]
> logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
> [web]
> push_ssl = false
> allow_push = *
> [phases]
> publish=False
> [extensions]
> drawdag=$TESTDIR/drawdag.py
> clonebundles=
> EOF
The extension requires a repo (currently unused)
$ hg init main
$ cd main
$ hg debugdrawdag <<'EOF'
> E
> |
> D
> |
> C
> |
> B
> |
> A
> EOF
$ hg bundle -a --type="none-v2;stream=v2" bundle.hg
$ hg debugbundle bundle.hg
Stream params: {}
stream2 -- {bytecount: 1693, filecount: 11, requirements: generaldelta%2Crevlogv1%2Csparserevlog} (mandatory: True) (no-zstd !)
stream2 -- {bytecount: 1693, filecount: 11, requirements: generaldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog} (mandatory: True) (zstd no-rust !)
stream2 -- {bytecount: 1693, filecount: 11, requirements: generaldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog} (mandatory: True) (rust !)
$ hg debugbundle --spec bundle.hg
none-v2;stream=v2;requirements%3Dgeneraldelta%2Crevlogv1%2Csparserevlog (no-zstd !)
none-v2;stream=v2;requirements%3Dgeneraldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog (zstd no-rust !)
none-v2;stream=v2;requirements%3Dgeneraldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog (rust !)
Test that we can apply the bundle as a stream clone bundle
$ cat > .hg/clonebundles.manifest << EOF
> http://localhost:$HGPORT1/bundle.hg BUNDLESPEC=`hg debugbundle --spec bundle.hg`
> EOF
$ hg serve -d -p $HGPORT --pid-file hg.pid --accesslog access.log
$ cat hg.pid >> $DAEMON_PIDS
$ "$PYTHON" $TESTDIR/dumbhttp.py -p $HGPORT1 --pid http.pid
$ cat http.pid >> $DAEMON_PIDS
$ cd ..
$ hg clone http://localhost:$HGPORT streamv2-clone-implicit --debug
using http://localhost:$HGPORT/
sending capabilities command
sending clonebundles command
applying clone bundle from http://localhost:$HGPORT1/bundle.hg
bundle2-input-bundle: with-transaction
bundle2-input-part: "stream2" (params: 3 mandatory) supported
applying stream bundle
11 files to transfer, 1.65 KB of data
starting 4 threads for background file closing (?)
starting 4 threads for background file closing (?)
adding [s] data/A.i (66 bytes)
adding [s] data/B.i (66 bytes)
adding [s] data/C.i (66 bytes)
adding [s] data/D.i (66 bytes)
adding [s] data/E.i (66 bytes)
adding [s] 00manifest.i (584 bytes)
adding [s] 00changelog.i (595 bytes)
adding [s] phaseroots (43 bytes)
adding [c] branch2-served (94 bytes)
adding [c] rbc-names-v1 (7 bytes)
adding [c] rbc-revs-v1 (40 bytes)
transferred 1.65 KB in * seconds (* */sec) (glob)
bundle2-input-part: total payload size 1840
bundle2-input-bundle: 1 parts total
updating the branch cache
finished applying clone bundle
query 1; heads
sending batch command
searching for changes
all remote heads known locally
no changes found
sending getbundle command
bundle2-input-bundle: with-transaction
bundle2-input-part: "listkeys" (params: 1 mandatory) supported
bundle2-input-part: "phase-heads" supported
bundle2-input-part: total payload size 24
bundle2-input-bundle: 2 parts total
checking for updated bookmarks
updating to branch default
resolving manifests
branchmerge: False, force: False, partial: False
ancestor: 000000000000, local: 000000000000+, remote: 9bc730a19041
A: remote created -> g
getting A
B: remote created -> g
getting B
C: remote created -> g
getting C
D: remote created -> g
getting D
E: remote created -> g
getting E
5 files updated, 0 files merged, 0 files removed, 0 files unresolved
updating the branch cache
(sent 4 HTTP requests and * bytes; received * bytes in responses) (glob)
$ hg clone --stream http://localhost:$HGPORT streamv2-clone-explicit --debug
using http://localhost:$HGPORT/
sending capabilities command
sending clonebundles command
applying clone bundle from http://localhost:$HGPORT1/bundle.hg
bundle2-input-bundle: with-transaction
bundle2-input-part: "stream2" (params: 3 mandatory) supported
applying stream bundle
11 files to transfer, 1.65 KB of data
starting 4 threads for background file closing (?)
starting 4 threads for background file closing (?)
adding [s] data/A.i (66 bytes)
adding [s] data/B.i (66 bytes)
adding [s] data/C.i (66 bytes)
adding [s] data/D.i (66 bytes)
adding [s] data/E.i (66 bytes)
adding [s] 00manifest.i (584 bytes)
adding [s] 00changelog.i (595 bytes)
adding [s] phaseroots (43 bytes)
adding [c] branch2-served (94 bytes)
adding [c] rbc-names-v1 (7 bytes)
adding [c] rbc-revs-v1 (40 bytes)
transferred 1.65 KB in * seconds (* */sec) (glob)
bundle2-input-part: total payload size 1840
bundle2-input-bundle: 1 parts total
updating the branch cache
finished applying clone bundle
query 1; heads
sending batch command
searching for changes
all remote heads known locally
no changes found
sending getbundle command
bundle2-input-bundle: with-transaction
bundle2-input-part: "listkeys" (params: 1 mandatory) supported
bundle2-input-part: "phase-heads" supported
bundle2-input-part: total payload size 24
bundle2-input-bundle: 2 parts total
checking for updated bookmarks
updating to branch default
resolving manifests
branchmerge: False, force: False, partial: False
ancestor: 000000000000, local: 000000000000+, remote: 9bc730a19041
A: remote created -> g
getting A
B: remote created -> g
getting B
C: remote created -> g
getting C
D: remote created -> g
getting D
E: remote created -> g
getting E
5 files updated, 0 files merged, 0 files removed, 0 files unresolved
updating the branch cache
(sent 4 HTTP requests and * bytes; received * bytes in responses) (glob)