Skip to content

Commit 526775f

Browse files
authored
perf: invalidate less contradicted_incompatibilities (pubgrub-rs#170)
* Invalidate less contradicted_incompatibilities * update comments
1 parent 516f033 commit 526775f

File tree

2 files changed

+22
-9
lines changed

2 files changed

+22
-9
lines changed

src/internal/core.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ pub struct State<P: Package, VS: VersionSet, Priority: Ord + Clone> {
2727

2828
incompatibilities: Map<P, Vec<IncompId<P, VS>>>,
2929

30-
/// Store the ids of incompatibilities that are already contradicted
31-
/// and will stay that way until the next conflict and backtrack is operated.
32-
contradicted_incompatibilities: rustc_hash::FxHashSet<IncompId<P, VS>>,
30+
/// Store the ids of incompatibilities that are already contradicted.
31+
/// For each one keep track of the decision level when it was found to be contradicted.
32+
/// These will stay contradicted until we have backtracked beyond its associated decision level.
33+
contradicted_incompatibilities: Map<IncompId<P, VS>, DecisionLevel>,
3334

3435
/// All incompatibilities expressing dependencies,
3536
/// with common dependents merged.
@@ -62,7 +63,7 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> State<P, VS, Priority> {
6263
root_package,
6364
root_version,
6465
incompatibilities,
65-
contradicted_incompatibilities: rustc_hash::FxHashSet::default(),
66+
contradicted_incompatibilities: Map::default(),
6667
partial_solution: PartialSolution::empty(),
6768
incompatibility_store,
6869
unit_propagation_buffer: SmallVec::Empty,
@@ -111,7 +112,10 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> State<P, VS, Priority> {
111112
let mut conflict_id = None;
112113
// We only care about incompatibilities if it contains the current package.
113114
for &incompat_id in self.incompatibilities[&current_package].iter().rev() {
114-
if self.contradicted_incompatibilities.contains(&incompat_id) {
115+
if self
116+
.contradicted_incompatibilities
117+
.contains_key(&incompat_id)
118+
{
115119
continue;
116120
}
117121
let current_incompat = &self.incompatibility_store[incompat_id];
@@ -135,10 +139,12 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> State<P, VS, Priority> {
135139
&self.incompatibility_store,
136140
);
137141
// With the partial solution updated, the incompatibility is now contradicted.
138-
self.contradicted_incompatibilities.insert(incompat_id);
142+
self.contradicted_incompatibilities
143+
.insert(incompat_id, self.partial_solution.current_decision_level());
139144
}
140145
Relation::Contradicted(_) => {
141-
self.contradicted_incompatibilities.insert(incompat_id);
146+
self.contradicted_incompatibilities
147+
.insert(incompat_id, self.partial_solution.current_decision_level());
142148
}
143149
_ => {}
144150
}
@@ -155,7 +161,8 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> State<P, VS, Priority> {
155161
);
156162
// After conflict resolution and the partial solution update,
157163
// the root cause incompatibility is now contradicted.
158-
self.contradicted_incompatibilities.insert(root_cause);
164+
self.contradicted_incompatibilities
165+
.insert(root_cause, self.partial_solution.current_decision_level());
159166
}
160167
}
161168
// If there are no more changed packages, unit propagation is done.
@@ -220,7 +227,9 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> State<P, VS, Priority> {
220227
) {
221228
self.partial_solution
222229
.backtrack(decision_level, &self.incompatibility_store);
223-
self.contradicted_incompatibilities.clear();
230+
// Remove contradicted incompatibilities that depend on decisions we just backtracked away.
231+
self.contradicted_incompatibilities
232+
.retain(|_, dl| *dl <= decision_level);
224233
if incompat_changed {
225234
self.merge_incompatibility(incompat);
226235
}

src/internal/partial_solution.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,10 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> PartialSolution<P, VS, P
493493
.unwrap();
494494
decision_level.max(DecisionLevel(1))
495495
}
496+
497+
pub fn current_decision_level(&self) -> DecisionLevel {
498+
self.current_decision_level
499+
}
496500
}
497501

498502
impl<P: Package, VS: VersionSet> PackageAssignments<P, VS> {

0 commit comments

Comments
 (0)