revset: optimize _firstancestors using Rust fast path

Summary:
Optimize the `_firstancestors` revset function using Rust.

When calculating `len(_firstancestors(master))`, the new code took 2ms while
the old code needs 76s, a ~40000x improvement.

Reviewed By: sfilipco

Differential Revision: D26182242

fbshipit-source-id: 55f17b014e727d8e8e3099b7c287f8bf8479279b
This commit is contained in:
Jun Wu 2021-02-05 11:50:59 -08:00 committed by Facebook GitHub Bot
parent 101f5066e0
commit cc123cc1ce
2 changed files with 10 additions and 0 deletions

View File

@ -561,6 +561,11 @@ def ancestors(repo, subset, x):
def _firstancestors(repo, subset, x):
# ``_firstancestors(set)``
# Like ``ancestors(set)`` but follows only the first parents.
cl = repo.changelog
if cl.userust("revset"):
s = getset(repo, fullreposet(repo), x)
result = cl.dag.firstancestors(cl.tonodes(s))
return subset & cl.torevset(result)
return _ancestors(repo, subset, x, followfirst=True)

View File

@ -31,6 +31,11 @@ py_class!(pub class dagalgo |py| {
Ok(Names(block_on(self.dag(py).ancestors(set.0)).map_pyerr(py)?))
}
/// Calculate all ancestors reachable from the set, following only first parents.
def firstancestors(&self, set: Names) -> PyResult<Names> {
Ok(Names(block_on(self.dag(py).first_ancestors(set.0)).map_pyerr(py)?))
}
/// Calculate parents of the given set.
def parents(&self, set: Names) -> PyResult<Names> {
Ok(Names(block_on(self.dag(py).parents(set.0)).map_pyerr(py)?))