Mercurial > hg
annotate tests/test-fuzz-targets.t @ 51681:522b4d729e89
mmap: populate the mapping by default
Without pre-population, accessing all data through a mmap can result in many
pagefault, reducing performance significantly. If the mmap is prepopulated, the
performance can no longer get slower than a full read.
(See benchmark number below)
In some cases were very few data is read, prepopulating can be overkill and
slower than populating on access (through page fault). So that behavior can be
controlled when the caller can pre-determine the best behavior.
(See benchmark number below)
In addition, testing with populating in a secondary thread yield great result
combining the best of each approach. This might be implemented in later
changesets.
In all cases, using mmap has a great effect on memory usage when many processes
run in parallel on the same machine.
### Benchmarks
# What did I run
A couple of month back I ran a large benchmark campaign to assess the impact of
various approach for using mmap with the revlog (and other files), it
highlighted a few benchmarks that capture the impact of the changes well. So to
validate this change I checked the following:
- log command displaying various revisions
(read the changelog index)
- log command displaying the patch of listed revisions
(read the changelog index, the manifest index and a few files indexes)
- unbundling a few revisions
(read and write changelog, manifest and few files indexes, and walk the graph
to update some cache)
- pushing a few revisions
(read and write changelog, manifest and few files indexes, walk the graph to
update some cache, performs various accesses locally and remotely during
discovery)
Benchmarks were run using the default module policy (c+py) and the rust one. No
significant difference were found between the two implementation, so we will
present result using the default policy (unless otherwise specified).
I ran them on a few repositories :
- mercurial: a "public changeset only" copy of mercurial from 2018-08-01 using
zstd compression and sparse-revlog
- pypy: a copy of pypy from 2018-08-01 using zstd compression and sparse-revlog
- netbeans: a copy of netbeans from 2018-08-01 using zstd compression and
sparse-revlog
- mozilla-try: a copy of mozilla-try from 2019-02-18 using zstd compression and
sparse-revlog
- mozilla-try persistent-nodemap: Same as the above but with a persistent
nodemap. Used for the log --patch benchmark only
# Results
For the smaller repositories (mercurial, pypy), the impact of mmap is almost
imperceptible, other cost dominating the operation. The impact of prepopulating
is undiscernible in the benchmark we ran.
For larger repositories the benchmark support explanation given above:
On netbeans, the log can be about 1% faster without repopulation (for a
difference < 100ms) but unbundle becomes a bit slower, even when small.
### data-env-vars.name = netbeans-2018-08-01-zstd-sparse-revlog
# benchmark.name = hg.command.unbundle
# benchmark.variants.issue6528 = disabled
# benchmark.variants.reuse-external-delta-parent = yes
# benchmark.variants.revs = any-1-extra-rev
# benchmark.variants.source = unbundle
# benchmark.variants.verbosity = quiet
with-populate: 0.240157
no-populate: 0.265087 (+10.38%, +0.02)
# benchmark.variants.revs = any-100-extra-rev
with-populate: 1.459518
no-populate: 1.481290 (+1.49%, +0.02)
## benchmark.name = hg.command.push
# benchmark.variants.explicit-rev = none
# benchmark.variants.issue6528 = disabled
# benchmark.variants.protocol = ssh
# benchmark.variants.reuse-external-delta-parent = yes
# benchmark.variants.revs = any-1-extra-rev
with-populate: 0.771919
no-populate: 0.792025 (+2.60%, +0.02)
# benchmark.variants.revs = any-100-extra-rev
with-populate: 1.459518
no-populate: 1.481290 (+1.49%, +0.02)
For mozilla-try, the "slow down" from pre-populate for small `hg log` is more
visible, but still small in absolute time. (using rust value for the persistent
nodemap value to be relevant).
### data-env-vars.name = mozilla-try-2019-02-18-ds2-pnm
# benchmark.name = hg.command.log
# bin-env-vars.hg.flavor = rust
# benchmark.variants.patch = yes
# benchmark.variants.limit-rev = 1
with-populate: 0.237813
no-populate: 0.229452 (-3.52%, -0.01)
# benchmark.variants.limit-rev = 10
# benchmark.variants.patch = yes
with-populate: 1.213578
no-populate: 1.205189
### data-env-vars.name = mozilla-try-2019-02-18-zstd-sparse-revlog
# benchmark.variants.limit-rev = 1000
# benchmark.variants.patch = no
# benchmark.variants.rev = tip
with-populate: 0.198607
no-populate: 0.195038 (-1.80%, -0.00)
However pre-populating provide a significant boost on more complex operations
like unbundle or push:
### data-env-vars.name = mozilla-try-2019-02-18-zstd-sparse-revlog
# benchmark.name = hg.command.push
# benchmark.variants.explicit-rev = none
# benchmark.variants.issue6528 = disabled
# benchmark.variants.protocol = ssh
# benchmark.variants.reuse-external-delta-parent = yes
# benchmark.variants.revs = any-1-extra-rev
with-populate: 4.798632
no-populate: 4.953295 (+3.22%, +0.15)
# benchmark.variants.revs = any-100-extra-rev
with-populate: 4.903618
no-populate: 5.014963 (+2.27%, +0.11)
## benchmark.name = hg.command.unbundle
# benchmark.variants.revs = any-1-extra-rev
with-populate: 1.423411
no-populate: 1.585365 (+11.38%, +0.16)
# benchmark.variants.revs = any-100-extra-rev
with-populate: 1.537909
no-populate: 1.688489 (+9.79%, +0.15)
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Thu, 11 Apr 2024 00:02:07 +0200 |
parents | 1d075b857c90 |
children |
rev | line source |
---|---|
46257
b918494198f7
fuzz: try and ensure fuzzer tests run against the right python-config
Augie Fackler <augie@google.com>
parents:
43815
diff
changeset
|
1 #require test-repo py3 |
38236
a6347ae6168d
test-fuzz-targets: look for clang-6.0 binary as well
Yuya Nishihara <yuya@tcha.org>
parents:
38235
diff
changeset
|
2 |
35670
2b9e2415f5b5
contrib: add some basic scaffolding for some fuzz test targets
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
3 $ cd $TESTDIR/../contrib/fuzz |
43815
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
4 $ OUT=$TESTTMP ; export OUT |
38236
a6347ae6168d
test-fuzz-targets: look for clang-6.0 binary as well
Yuya Nishihara <yuya@tcha.org>
parents:
38235
diff
changeset
|
5 |
40726
6c01fad8de32
tests: sniff for /usr/local/bin/gmake and use it in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
38246
diff
changeset
|
6 which(1) could exit nonzero, but that's fine because we'll still end |
6c01fad8de32
tests: sniff for /usr/local/bin/gmake and use it in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
38246
diff
changeset
|
7 up without a valid executable, so we don't need to check $? here. |
6c01fad8de32
tests: sniff for /usr/local/bin/gmake and use it in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
38246
diff
changeset
|
8 |
6c01fad8de32
tests: sniff for /usr/local/bin/gmake and use it in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
38246
diff
changeset
|
9 $ if which gmake >/dev/null 2>&1; then |
6c01fad8de32
tests: sniff for /usr/local/bin/gmake and use it in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
38246
diff
changeset
|
10 > MAKE=gmake |
6c01fad8de32
tests: sniff for /usr/local/bin/gmake and use it in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
38246
diff
changeset
|
11 > else |
6c01fad8de32
tests: sniff for /usr/local/bin/gmake and use it in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
38246
diff
changeset
|
12 > MAKE=make |
6c01fad8de32
tests: sniff for /usr/local/bin/gmake and use it in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
38246
diff
changeset
|
13 > fi |
6c01fad8de32
tests: sniff for /usr/local/bin/gmake and use it in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
38246
diff
changeset
|
14 |
40727
d9fc51f77cc5
tests: sniff for libfuzzer actually being available in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40726
diff
changeset
|
15 $ havefuzz() { |
d9fc51f77cc5
tests: sniff for libfuzzer actually being available in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40726
diff
changeset
|
16 > cat > $TESTTMP/dummy.cc <<EOF |
d9fc51f77cc5
tests: sniff for libfuzzer actually being available in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40726
diff
changeset
|
17 > #include <stdlib.h> |
d9fc51f77cc5
tests: sniff for libfuzzer actually being available in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40726
diff
changeset
|
18 > #include <stdint.h> |
d9fc51f77cc5
tests: sniff for libfuzzer actually being available in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40726
diff
changeset
|
19 > int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return 0; } |
d9fc51f77cc5
tests: sniff for libfuzzer actually being available in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40726
diff
changeset
|
20 > int main(int argc, char **argv) { |
d9fc51f77cc5
tests: sniff for libfuzzer actually being available in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40726
diff
changeset
|
21 > const char data[] = "asdf"; |
d9fc51f77cc5
tests: sniff for libfuzzer actually being available in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40726
diff
changeset
|
22 > return LLVMFuzzerTestOneInput((const uint8_t *)data, 4); |
d9fc51f77cc5
tests: sniff for libfuzzer actually being available in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40726
diff
changeset
|
23 > } |
d9fc51f77cc5
tests: sniff for libfuzzer actually being available in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40726
diff
changeset
|
24 > EOF |
d9fc51f77cc5
tests: sniff for libfuzzer actually being available in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40726
diff
changeset
|
25 > $CXX $TESTTMP/dummy.cc -o $TESTTMP/dummy \ |
d9fc51f77cc5
tests: sniff for libfuzzer actually being available in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40726
diff
changeset
|
26 > -fsanitize=fuzzer-no-link,address || return 1 |
d9fc51f77cc5
tests: sniff for libfuzzer actually being available in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40726
diff
changeset
|
27 > } |
d9fc51f77cc5
tests: sniff for libfuzzer actually being available in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40726
diff
changeset
|
28 |
46257
b918494198f7
fuzz: try and ensure fuzzer tests run against the right python-config
Augie Fackler <augie@google.com>
parents:
43815
diff
changeset
|
29 Try to find a python3-config that's next to our sys.executable. If |
b918494198f7
fuzz: try and ensure fuzzer tests run against the right python-config
Augie Fackler <augie@google.com>
parents:
43815
diff
changeset
|
30 that doesn't work, fall back to looking for a global python3-config |
b918494198f7
fuzz: try and ensure fuzzer tests run against the right python-config
Augie Fackler <augie@google.com>
parents:
43815
diff
changeset
|
31 and hope that works out for the best. |
47063
1d075b857c90
tests: ensure `$PYTHON` is quoted for Windows
Matt Harbison <matt_harbison@yahoo.com>
parents:
46257
diff
changeset
|
32 $ PYBIN=`"$PYTHON" -c 'import sys, os; print(os.path.dirname(sys.executable))'` |
46257
b918494198f7
fuzz: try and ensure fuzzer tests run against the right python-config
Augie Fackler <augie@google.com>
parents:
43815
diff
changeset
|
33 $ if [ -x "$PYBIN/python3-config" ] ; then |
b918494198f7
fuzz: try and ensure fuzzer tests run against the right python-config
Augie Fackler <augie@google.com>
parents:
43815
diff
changeset
|
34 > PYTHON_CONFIG="$PYBIN/python3-config" |
b918494198f7
fuzz: try and ensure fuzzer tests run against the right python-config
Augie Fackler <augie@google.com>
parents:
43815
diff
changeset
|
35 > else |
b918494198f7
fuzz: try and ensure fuzzer tests run against the right python-config
Augie Fackler <augie@google.com>
parents:
43815
diff
changeset
|
36 > PYTHON_CONFIG="`which python3-config`" |
b918494198f7
fuzz: try and ensure fuzzer tests run against the right python-config
Augie Fackler <augie@google.com>
parents:
43815
diff
changeset
|
37 > fi |
b918494198f7
fuzz: try and ensure fuzzer tests run against the right python-config
Augie Fackler <augie@google.com>
parents:
43815
diff
changeset
|
38 |
38236
a6347ae6168d
test-fuzz-targets: look for clang-6.0 binary as well
Yuya Nishihara <yuya@tcha.org>
parents:
38235
diff
changeset
|
39 #if clang-libfuzzer |
40727
d9fc51f77cc5
tests: sniff for libfuzzer actually being available in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40726
diff
changeset
|
40 $ CXX=clang++ havefuzz || exit 80 |
46257
b918494198f7
fuzz: try and ensure fuzzer tests run against the right python-config
Augie Fackler <augie@google.com>
parents:
43815
diff
changeset
|
41 $ $MAKE -s clean all PYTHON_CONFIG="$PYTHON_CONFIG" |
38236
a6347ae6168d
test-fuzz-targets: look for clang-6.0 binary as well
Yuya Nishihara <yuya@tcha.org>
parents:
38235
diff
changeset
|
42 #endif |
a6347ae6168d
test-fuzz-targets: look for clang-6.0 binary as well
Yuya Nishihara <yuya@tcha.org>
parents:
38235
diff
changeset
|
43 #if no-clang-libfuzzer clang-6.0 |
40727
d9fc51f77cc5
tests: sniff for libfuzzer actually being available in test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40726
diff
changeset
|
44 $ CXX=clang++-6.0 havefuzz || exit 80 |
46257
b918494198f7
fuzz: try and ensure fuzzer tests run against the right python-config
Augie Fackler <augie@google.com>
parents:
43815
diff
changeset
|
45 $ $MAKE -s clean all CC=clang-6.0 CXX=clang++-6.0 PYTHON_CONFIG="$PYTHON_CONFIG" |
38236
a6347ae6168d
test-fuzz-targets: look for clang-6.0 binary as well
Yuya Nishihara <yuya@tcha.org>
parents:
38235
diff
changeset
|
46 #endif |
a6347ae6168d
test-fuzz-targets: look for clang-6.0 binary as well
Yuya Nishihara <yuya@tcha.org>
parents:
38235
diff
changeset
|
47 #if no-clang-libfuzzer no-clang-6.0 |
a6347ae6168d
test-fuzz-targets: look for clang-6.0 binary as well
Yuya Nishihara <yuya@tcha.org>
parents:
38235
diff
changeset
|
48 $ exit 80 |
a6347ae6168d
test-fuzz-targets: look for clang-6.0 binary as well
Yuya Nishihara <yuya@tcha.org>
parents:
38235
diff
changeset
|
49 #endif |
a6347ae6168d
test-fuzz-targets: look for clang-6.0 binary as well
Yuya Nishihara <yuya@tcha.org>
parents:
38235
diff
changeset
|
50 |
43815
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
51 $ cd $TESTTMP |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
52 |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
53 Run each fuzzer using dummy.cc as a fake input, to make sure it runs |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
54 at all. In the future we should instead unpack the corpus for each |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
55 fuzzer and use that instead. |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
56 |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
57 $ for fuzzer in `ls *_fuzzer | sort` ; do |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
58 > echo run $fuzzer... |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
59 > ./$fuzzer dummy.cc > /dev/null 2>&1 |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
60 > done |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
61 run bdiff_fuzzer... |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
62 run dirs_fuzzer... |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
63 run dirstate_fuzzer... |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
64 run fm1readmarkers_fuzzer... |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
65 run fncache_fuzzer... |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
66 run jsonescapeu8fast_fuzzer... |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
67 run manifest_fuzzer... |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
68 run mpatch_fuzzer... |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
69 run revlog_fuzzer... |
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
70 run xdiff_fuzzer... |
42948
39cab871e880
tests: clean up built binaries after running test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40727
diff
changeset
|
71 |
39cab871e880
tests: clean up built binaries after running test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40727
diff
changeset
|
72 Clean up. |
43815
19da643dc10c
tests: finally fix up test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
42948
diff
changeset
|
73 $ cd $TESTDIR/../contrib/fuzz |
42948
39cab871e880
tests: clean up built binaries after running test-fuzz-targets.t
Augie Fackler <augie@google.com>
parents:
40727
diff
changeset
|
74 $ $MAKE -s clean |