revset: ad-hoc optimization for range queries containing unwanted wanted heads

In my linux stable mirror, this makes the default log revset evaluation super
fast. immutable_heads(), if configured properly, includes many historical
branch heads which are also the visible heads.

revsets/immutable_heads()..
---------------------------
0     12.27     117.1±0.77m
3      1.00       9.5±0.08m
This commit is contained in:
Yuya Nishihara 2024-02-19 22:54:10 +09:00
parent f71f065b17
commit f21c078249
2 changed files with 11 additions and 1 deletions

View File

@ -16,6 +16,8 @@ v2.39.0::v2.40.0
# Tags and branches
tags()
branches()
# Local changes
(tags() | remote_branches())..
# Intersection of range with a small subset
tags() & ::v2.40.0
v2.39.0 & ::v2.40.0

View File

@ -764,8 +764,16 @@ impl<'index> EvaluationContext<'index> {
} => {
let root_set = self.evaluate(roots)?;
let root_positions = root_set.positions(index).collect_vec();
// Pre-filter heads so queries like 'immutable_heads()..' can
// terminate early. immutable_heads() usually includes some
// visible heads, which can be trivially rejected.
let head_set = self.evaluate(heads)?;
let head_positions = head_set.positions(index).collect_vec();
let head_positions = difference_by(
head_set.positions(index),
root_positions.iter().copied(),
|pos1, pos2| pos1.cmp(pos2).reverse(),
)
.collect_vec();
if generation == &GENERATION_RANGE_FULL {
Ok(Box::new(RevWalkRevset::new(move |index| {
Box::new(index.walk_revs(&head_positions, &root_positions))