Page MenuHomePhabricator

rust-discovery: using the children cache in add_missing
Needs ReviewPublic

Authored by gracinet on Wed, May 22, 1:00 PM.

Details

Reviewers
kevincox
Group Reviewers
hg-reviewers
Summary

The DAG range computation often needs to get back to very old
revisions, and turns out to be disproportionately long, given
that the end goal is to remove the descendents of the given
missing revisons from the undecided set.

The fast iteration capabilities available in the Rust case make
it possible to avoid the DAG range entirely, at the cost of
precomputing the children cache, and to simply iterate on
children of the given missing revisions.

This is a case where staying on the same side of the interface
between the two languages has clear benefits.

On discoveries with initial undecided sets
small enough to bypass sampling entirely, the total cost of
computing the children cache and the subsequent iteration
becomes better than the Python + C counterpart, which relies on
reachableroots2.

For example, on a repo with more than one million revisions with
an initial undecided set of 11 elements, we get these figures:

Rust version with simple iteration

addcommons: 57.287us
first undecided computation: 184.278334ms
first children cache computation: 131.056us
addmissings iteration: 42.766us
first addinfo total: 185.24 ms

Python + C version

first addcommons: 0.29 ms
addcommons 0.21 ms
first undecided computation 191.35 ms
addmissings 45.75 ms
first addinfo total: 237.77 ms

On discoveries with large undecided sets, the initial price paid
makes the first addinfo slower than the Python + C version,
but that's more than compensated by the gain in sampling and
subsequent iterations.
Here's an extreme example with an undecided set of a million revisions:

Rust version:

first undecided computation: 293.842629ms
first children cache computation: 407.911297ms
addmissings iteration: 34.312869ms
first addinfo total: 776.02 ms
taking initial sample
query 2: sampling time: 1318.38 ms
query 2; still undecided: 1005013, sample size is: 200
addmissings: 143.062us

Python + C version:

first undecided computation 298.13 ms
addmissings 80.13 ms
first addinfo total: 399.62 ms
taking initial sample
query 2: sampling time: 3957.23 ms
query 2; still undecided: 1005013, sample size is: 200
addmissings 52.88 ms

Diff Detail

Repository
rHG Mercurial
Lint
Lint Skipped
Unit
Unit Tests Skipped

Event Timeline

gracinet created this revision.Wed, May 22, 1:00 PM

This revision is new. At the time I submitted the previous series, it was almost always the case that the advantage of the C reachableroots2() over the Rust `dagop::range() was more than compensated by sampling been done in Rust instead of Python.
I originally planned to finish that one and submit it as a follow-up optimization, but now it's necessary to prevent being slower in the fastest cases where there's no sampling.

kevincox accepted this revision.Mon, Jun 10, 8:59 AM
kevincox added inline comments.
rust/hg-core/src/discovery.rs
243

These added comments seem more relevant to the implementation of the method than they are to the caller. Would it make sense to move them inside of the function body so that they don't busy the doc-comment?

gracinet updated this revision to Diff 15471.Wed, Jun 12, 2:17 PM
gracinet updated this revision to Diff 15485.Thu, Jun 13, 9:33 AM
gracinet added inline comments.Thu, Jun 13, 9:38 AM
rust/hg-core/src/discovery.rs
243

Yes, you're right, I replaced it with a "Performance note" section for the callers.
As for the rationale for the change, I think that the commit message is more than enough.