… that runs in parallel with the parent thread fetching data.
This can be disabled through a new config. CLI example:
hg --config=devel.copy-tracing.multi-thread=no
For now both threads use the GIL, later commits will reduce this.
… that runs in parallel with the parent thread fetching data.
This can be disabled through a new config. CLI example:
hg --config=devel.copy-tracing.multi-thread=no
For now both threads use the GIL, later commits will reduce this.
No Linters Available |
No Unit Test Coverage |
rust/hg-cpython/src/copy_tracing.rs | ||
---|---|---|
54 | This is a better comment, I almost said something on the last commit | |
78 | This will not honor the RAYON_NUM_THREADS environment variable that we use to contain the number of threads in tests, but also technically for users as an implementation detail. Should we use rayon threads here so as to have the same threadpool everywhere? |
rust/hg-cpython/src/copy_tracing.rs | ||
---|---|---|
54 | This was a pre-existing comment, the previous commit only moved it around. But yeah I could have included this change in the previous commit. | |
78 | I feel that starting a pool of multiple thread to run a single task on it and leaving it running until process exit is counter-productive compared to the one thread started and then stopped here. Unless combine_changeset_copies_wrapper itself is called with high concurrency from many Python threads (which would contend the GIL) we’re not gonna have many of these Rust threads. |
Path | Packages | |||
---|---|---|---|---|
M | mercurial/configitems.py (5 lines) | |||
M | mercurial/copies.py (13 lines) | |||
M | rust/Cargo.lock (1 line) | |||
M | rust/hg-cpython/Cargo.toml (1 line) | |||
M | rust/hg-cpython/src/copy_tracing.rs (89 lines) |
Commit | Parents | Author | Summary | Date |
---|---|---|---|---|
f794d0f0c62a | 4ba3c46e714d | Simon Sapin | Jan 6 2021, 8:09 AM |
) | ) | ||||
coreconfigitem( | coreconfigitem( | ||||
b'devel', | b'devel', | ||||
b'debug.copies', | b'debug.copies', | ||||
default=False, | default=False, | ||||
) | ) | ||||
coreconfigitem( | coreconfigitem( | ||||
b'devel', | b'devel', | ||||
b'copy-tracing.multi-thread', | |||||
default=True, | |||||
) | |||||
coreconfigitem( | |||||
b'devel', | |||||
b'debug.extensions', | b'debug.extensions', | ||||
default=False, | default=False, | ||||
) | ) | ||||
coreconfigitem( | coreconfigitem( | ||||
b'devel', | b'devel', | ||||
b'debug.repo-filters', | b'debug.repo-filters', | ||||
default=False, | default=False, | ||||
) | ) |
parents = cl._uncheckedparentrevs | parents = cl._uncheckedparentrevs | ||||
graph_roots = (nullrev, nullrev) | graph_roots = (nullrev, nullrev) | ||||
ancestors = cl.ancestors([a.rev()], inclusive=True) | ancestors = cl.ancestors([a.rev()], inclusive=True) | ||||
revs = cl.findmissingrevs(common=[a.rev()], heads=[b.rev()]) | revs = cl.findmissingrevs(common=[a.rev()], heads=[b.rev()]) | ||||
roots = set() | roots = set() | ||||
has_graph_roots = False | has_graph_roots = False | ||||
multi_thread = repo.ui.configbool(b'devel', b'copy-tracing.multi-thread') | |||||
# iterate over `only(B, A)` | # iterate over `only(B, A)` | ||||
for r in revs: | for r in revs: | ||||
ps = parents(r) | ps = parents(r) | ||||
if ps == graph_roots: | if ps == graph_roots: | ||||
has_graph_roots = True | has_graph_roots = True | ||||
else: | else: | ||||
p1, p2 = ps | p1, p2 = ps | ||||
for p in cl.parentrevs(r): | for p in cl.parentrevs(r): | ||||
if p == nullrev: | if p == nullrev: | ||||
continue | continue | ||||
children_count[r] = 0 | children_count[r] = 0 | ||||
if p in children_count: | if p in children_count: | ||||
children_count[p] += 1 | children_count[p] += 1 | ||||
revinfo = _revinfo_getter(repo, match) | revinfo = _revinfo_getter(repo, match) | ||||
return _combine_changeset_copies( | return _combine_changeset_copies( | ||||
revs, children_count, b.rev(), revinfo, match, isancestor | revs, | ||||
children_count, | |||||
b.rev(), | |||||
revinfo, | |||||
match, | |||||
isancestor, | |||||
multi_thread, | |||||
) | ) | ||||
else: | else: | ||||
# When not using side-data, we will process the edges "from" the parent. | # When not using side-data, we will process the edges "from" the parent. | ||||
# so we need a full mapping of the parent -> children relation. | # so we need a full mapping of the parent -> children relation. | ||||
children = dict((r, []) for r in roots) | children = dict((r, []) for r in roots) | ||||
for r in revs: | for r in revs: | ||||
for p in cl.parentrevs(r): | for p in cl.parentrevs(r): | ||||
if p == nullrev: | if p == nullrev: | ||||
continue | continue | ||||
children[r] = [] | children[r] = [] | ||||
if p in children: | if p in children: | ||||
children[p].append(r) | children[p].append(r) | ||||
x = revs.pop() | x = revs.pop() | ||||
assert x == b.rev() | assert x == b.rev() | ||||
revs.extend(roots) | revs.extend(roots) | ||||
revs.sort() | revs.sort() | ||||
revinfo = _revinfo_getter_extra(repo) | revinfo = _revinfo_getter_extra(repo) | ||||
return _combine_changeset_copies_extra( | return _combine_changeset_copies_extra( | ||||
revs, children, b.rev(), revinfo, match, isancestor | revs, children, b.rev(), revinfo, match, isancestor | ||||
) | ) | ||||
def _combine_changeset_copies( | def _combine_changeset_copies( | ||||
revs, children_count, targetrev, revinfo, match, isancestor | revs, children_count, targetrev, revinfo, match, isancestor, multi_thread | ||||
): | ): | ||||
"""combine the copies information for each item of iterrevs | """combine the copies information for each item of iterrevs | ||||
revs: sorted iterable of revision to visit | revs: sorted iterable of revision to visit | ||||
children_count: a {parent: <number-of-relevant-children>} mapping. | children_count: a {parent: <number-of-relevant-children>} mapping. | ||||
targetrev: the final copies destination revision (not in iterrevs) | targetrev: the final copies destination revision (not in iterrevs) | ||||
revinfo(rev): a function that return (p1, p2, p1copies, p2copies, removed) | revinfo(rev): a function that return (p1, p2, p1copies, p2copies, removed) | ||||
match: a matcher | match: a matcher | ||||
It returns the aggregated copies information for `targetrev`. | It returns the aggregated copies information for `targetrev`. | ||||
""" | """ | ||||
alwaysmatch = match.always() | alwaysmatch = match.always() | ||||
if rustmod is not None: | if rustmod is not None: | ||||
final_copies = rustmod.combine_changeset_copies( | final_copies = rustmod.combine_changeset_copies( | ||||
list(revs), children_count, targetrev, revinfo | list(revs), children_count, targetrev, revinfo, multi_thread | ||||
) | ) | ||||
else: | else: | ||||
isancestor = cached_is_ancestor(isancestor) | isancestor = cached_is_ancestor(isancestor) | ||||
all_copies = {} | all_copies = {} | ||||
# iterate over all the "children" side of copy tracing "edge" | # iterate over all the "children" side of copy tracing "edge" | ||||
for current_rev in revs: | for current_rev in revs: | ||||
p1, p2, changes = revinfo(current_rev) | p1, p2, changes = revinfo(current_rev) |
"zstd 0.5.3+zstd.1.4.5 (registry+https://github.com/rust-lang/crates.io-index)", | "zstd 0.5.3+zstd.1.4.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
] | ] | ||||
[[package]] | [[package]] | ||||
name = "hg-cpython" | name = "hg-cpython" | ||||
version = "0.1.0" | version = "0.1.0" | ||||
dependencies = [ | dependencies = [ | ||||
"cpython 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", | "cpython 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
"crossbeam-channel 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", | |||||
"env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", | "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
"hg-core 0.1.0", | "hg-core 0.1.0", | ||||
"libc 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)", | "libc 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", | "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
] | ] | ||||
[[package]] | [[package]] | ||||
name = "home" | name = "home" |
python3 = ["cpython/python3-sys", "cpython/extension-module"] | python3 = ["cpython/python3-sys", "cpython/extension-module"] | ||||
# Enable one of these features to build a test executable linked to libpython: | # Enable one of these features to build a test executable linked to libpython: | ||||
# e.g. cargo test --no-default-features --features python27-bin | # e.g. cargo test --no-default-features --features python27-bin | ||||
python27-bin = ["cpython/python27-sys"] | python27-bin = ["cpython/python27-sys"] | ||||
python3-bin = ["cpython/python3-sys"] | python3-bin = ["cpython/python3-sys"] | ||||
[dependencies] | [dependencies] | ||||
crossbeam-channel = "0.4" | |||||
hg-core = { path = "../hg-core"} | hg-core = { path = "../hg-core"} | ||||
libc = '*' | libc = '*' | ||||
log = "0.4.8" | log = "0.4.8" | ||||
env_logger = "0.7.1" | env_logger = "0.7.1" | ||||
[dependencies.cpython] | [dependencies.cpython] | ||||
version = "0.4.1" | version = "0.4.1" | ||||
default-features = false | default-features = false |
This is a better comment, I almost said something on the last commit