Mercurial > hg
view tests/test-sparse-import.t @ 38732:be4984261611
merge: mark file gets as not thread safe (issue5933)
In default installs, this has the effect of disabling the thread-based
worker on Windows when manifesting files in the working directory. My
measurements have shown that with revlog-based repositories, Mercurial
spends a lot of CPU time in revlog code resolving file data. This ends
up incurring a lot of context switching across threads and slows down
`hg update` operations when going from an empty working directory to
the tip of the repo.
On mozilla-unified (246,351 files) on an i7-6700K (4+4 CPUs):
before: 487s wall
after: 360s wall (equivalent to worker.enabled=false)
cpus=2: 379s wall
Even with only 2 threads, the thread pool is still slower.
The introduction of the thread-based worker (02b36e860e0b) states that
it resulted in a "~50%" speedup for `hg sparse --enable-profile` and
`hg sparse --disable-profile`. This disagrees with my measurement
above. I theorize a few reasons for this:
1) Removal of files from the working directory is I/O - not CPU - bound
and should benefit from a thread pool (unless I/O is insanely fast
and the GIL release is near instantaneous). So tests like `hg sparse
--enable-profile` may exercise deletion throughput and aren't good
benchmarks for worker tasks that are CPU heavy.
2) The patch was authored by someone at Facebook. The results were
likely measured against a repository using remotefilelog. And I
believe that revision retrieval during working directory updates with
remotefilelog will often use a remote store, thus being I/O and not
CPU bound. This probably resulted in an overstated performance gain.
Since there appears to be a need to enable the thread-based worker with
some stores, I've made the flagging of file gets as thread safe
configurable. I've made it experimental because I don't want to formalize
a boolean flag for this option and because this attribute is best
captured against the store implementation. But we don't have a proper
store API for this yet. I'd rather cross this bridge later.
It is possible there are revlog-based repositories that do benefit from
a thread-based worker. I didn't do very comprehensive testing. If there
are, we may want to devise a more proper algorithm for whether to use
the thread-based worker, including possibly config options to limit the
number of threads to use. But until I see evidence that justifies
complexity, simplicity wins.
Differential Revision: https://phab.mercurial-scm.org/D3963
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Wed, 18 Jul 2018 09:49:34 -0700 |
parents | 33d0859c37bd |
children | 5c2a4f37eace |
line wrap: on
line source
test sparse $ hg init myrepo $ cd myrepo $ cat >> $HGRCPATH <<EOF > [extensions] > sparse= > purge= > strip= > rebase= > EOF $ echo a > index.html $ echo x > data.py $ echo z > readme.txt $ cat > base.sparse <<EOF > [include] > *.sparse > EOF $ hg ci -Aqm 'initial' $ cat > webpage.sparse <<EOF > %include base.sparse > [include] > *.html > EOF $ hg ci -Aqm 'initial' Import a rules file against a 'blank' sparse profile $ cat > $TESTTMP/rules_to_import <<EOF > [include] > *.py > EOF $ hg debugsparse --import-rules $TESTTMP/rules_to_import $ ls data.py $ hg debugsparse --reset $ rm .hg/sparse $ cat > $TESTTMP/rules_to_import <<EOF > %include base.sparse > [include] > *.py > EOF $ hg debugsparse --import-rules $TESTTMP/rules_to_import $ ls base.sparse data.py webpage.sparse $ hg debugsparse --reset $ rm .hg/sparse Start against an existing profile; rules *already active* should be ignored $ hg debugsparse --enable-profile webpage.sparse $ hg debugsparse --include *.py $ cat > $TESTTMP/rules_to_import <<EOF > %include base.sparse > [include] > *.html > *.txt > [exclude] > *.py > EOF $ hg debugsparse --import-rules $TESTTMP/rules_to_import $ ls base.sparse index.html readme.txt webpage.sparse $ cat .hg/sparse %include webpage.sparse [include] *.py *.txt [exclude] *.py $ hg debugsparse --reset $ rm .hg/sparse Same tests, with -Tjson enabled to output summaries $ cat > $TESTTMP/rules_to_import <<EOF > [include] > *.py > EOF $ hg debugsparse --import-rules $TESTTMP/rules_to_import -Tjson [ { "exclude_rules_added": 0, "files_added": 0, "files_conflicting": 0, "files_dropped": 4, "include_rules_added": 1, "profiles_added": 0 } ] $ hg debugsparse --reset $ rm .hg/sparse $ cat > $TESTTMP/rules_to_import <<EOF > %include base.sparse > [include] > *.py > EOF $ hg debugsparse --import-rules $TESTTMP/rules_to_import -Tjson [ { "exclude_rules_added": 0, "files_added": 0, "files_conflicting": 0, "files_dropped": 2, "include_rules_added": 1, "profiles_added": 1 } ] $ hg debugsparse --reset $ rm .hg/sparse $ hg debugsparse --enable-profile webpage.sparse $ hg debugsparse --include *.py $ cat > $TESTTMP/rules_to_import <<EOF > %include base.sparse > [include] > *.html > *.txt > [exclude] > *.py > EOF $ hg debugsparse --import-rules $TESTTMP/rules_to_import -Tjson [ { "exclude_rules_added": 1, "files_added": 1, "files_conflicting": 0, "files_dropped": 1, "include_rules_added": 1, "profiles_added": 0 } ] If importing results in no new rules being added, no refresh should take place! $ cat > $TESTTMP/trap_sparse_refresh.py <<EOF > from mercurial import error, sparse > def extsetup(ui): > def abort_refresh(*args, **kwargs): > raise error.Abort('sparse._refresh called!') > sparse.refreshwdir = abort_refresh > EOF $ cat >> $HGRCPATH <<EOF > [extensions] > trap_sparse_refresh=$TESTTMP/trap_sparse_refresh.py > EOF $ cat > $TESTTMP/rules_to_import <<EOF > [include] > *.py > EOF $ hg debugsparse --import-rules $TESTTMP/rules_to_import If an exception is raised during refresh, restore the existing rules again. $ cat > $TESTTMP/rules_to_import <<EOF > [exclude] > *.html > EOF $ hg debugsparse --import-rules $TESTTMP/rules_to_import abort: sparse._refresh called! [255] $ cat .hg/sparse %include webpage.sparse [include] *.py *.txt [exclude] *.py