Skip to content

Commit cca4d45

Browse files
committed
move the BinaryHeap/pop_most_constrained code out of the most complicated loop
1 parent bcd0ead commit cca4d45

File tree

2 files changed

+49
-32
lines changed

2 files changed

+49
-32
lines changed

src/cargo/core/resolver/mod.rs

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
//! that we're implementing something that probably shouldn't be allocating all
4848
//! over the place.
4949
50-
use std::collections::{BTreeMap, BinaryHeap, HashMap, HashSet};
50+
use std::collections::{BTreeMap, HashMap, HashSet};
5151
use std::mem;
5252
use std::rc::Rc;
5353
use std::time::{Duration, Instant};
@@ -64,7 +64,7 @@ use util::profile;
6464

6565
use self::context::{Activations, Context};
6666
use self::types::{ActivateError, ActivateResult, Candidate, ConflictReason, DepsFrame, GraphNode};
67-
use self::types::{RcVecIter, RegistryQueryer, ResolverProgress};
67+
use self::types::{RcVecIter, RegistryQueryer, RemainingDeps, ResolverProgress};
6868

6969
pub use self::encode::{EncodableDependency, EncodablePackageId, EncodableResolve};
7070
pub use self::encode::{Metadata, WorkspaceResolve};
@@ -170,15 +170,8 @@ fn activate_deps_loop(
170170
summaries: &[(Summary, Method)],
171171
config: Option<&Config>,
172172
) -> CargoResult<Context> {
173-
// Note that a `BinaryHeap` is used for the remaining dependencies that need
174-
// activation. This heap is sorted such that the "largest value" is the most
175-
// constrained dependency, or the one with the least candidates.
176-
//
177-
// This helps us get through super constrained portions of the dependency
178-
// graph quickly and hopefully lock down what later larger dependencies can
179-
// use (those with more candidates).
180173
let mut backtrack_stack = Vec::new();
181-
let mut remaining_deps = BinaryHeap::new();
174+
let mut remaining_deps = RemainingDeps::new();
182175

183176
// `past_conflicting_activations` is a cache of the reasons for each time we
184177
// backtrack.
@@ -215,27 +208,15 @@ fn activate_deps_loop(
215208
// its own dependencies in turn. The `backtrack_stack` is a side table of
216209
// backtracking states where if we hit an error we can return to in order to
217210
// attempt to continue resolving.
218-
while let Some(mut deps_frame) = remaining_deps.pop() {
211+
while let Some((just_here_for_the_error_messages, frame)) =
212+
remaining_deps.pop_most_constrained()
213+
{
214+
let (mut parent, (mut cur, (mut dep, candidates, mut features))) = frame;
215+
219216
// If we spend a lot of time here (we shouldn't in most cases) then give
220217
// a bit of a visual indicator as to what we're doing.
221218
printed.shell_status(config)?;
222219

223-
let just_here_for_the_error_messages = deps_frame.just_for_error_messages;
224-
225-
// Figure out what our next dependency to activate is, and if nothing is
226-
// listed then we're entirely done with this frame (yay!) and we can
227-
// move on to the next frame.
228-
let frame = match deps_frame.remaining_siblings.next() {
229-
Some(sibling) => {
230-
let parent = Summary::clone(&deps_frame.parent);
231-
remaining_deps.push(deps_frame);
232-
(parent, sibling)
233-
}
234-
None => continue,
235-
};
236-
let (mut parent, (mut cur, (mut dep, candidates, mut features))) = frame;
237-
assert!(!remaining_deps.is_empty());
238-
239220
trace!(
240221
"{}[{}]>{} {} candidates",
241222
parent.name(),
@@ -365,7 +346,7 @@ fn activate_deps_loop(
365346
Some(BacktrackFrame {
366347
cur,
367348
context_backup: Context::clone(&cx),
368-
deps_backup: <BinaryHeap<DepsFrame>>::clone(&remaining_deps),
349+
deps_backup: remaining_deps.clone(),
369350
remaining_candidates: remaining_candidates.clone(),
370351
parent: Summary::clone(&parent),
371352
dep: Dependency::clone(&dep),
@@ -453,7 +434,6 @@ fn activate_deps_loop(
453434
{
454435
if let Some((other_parent, conflict)) = remaining_deps
455436
.iter()
456-
.flat_map(|other| other.flatten())
457437
// for deps related to us
458438
.filter(|&(_, ref other_dep)| {
459439
known_related_bad_deps.contains(other_dep)
@@ -650,7 +630,7 @@ fn activate(
650630
struct BacktrackFrame {
651631
cur: usize,
652632
context_backup: Context,
653-
deps_backup: BinaryHeap<DepsFrame>,
633+
deps_backup: RemainingDeps,
654634
remaining_candidates: RemainingCandidates,
655635
parent: Summary,
656636
dep: Dependency,

src/cargo/core/resolver/types.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::cmp::Ordering;
2-
use std::collections::{HashMap, HashSet};
2+
use std::collections::{BinaryHeap, HashMap, HashSet};
33
use std::ops::Range;
44
use std::rc::Rc;
55
use std::time::{Duration, Instant};
@@ -272,7 +272,7 @@ impl DepsFrame {
272272
.unwrap_or(0)
273273
}
274274

275-
pub fn flatten<'s>(&'s self) -> impl Iterator<Item = (&PackageId, Dependency)> + 's {
275+
pub fn flatten(&self) -> impl Iterator<Item = (&PackageId, Dependency)> {
276276
self.remaining_siblings
277277
.clone()
278278
.map(move |(_, (d, _, _))| (self.parent.package_id(), d))
@@ -306,6 +306,43 @@ impl Ord for DepsFrame {
306306
}
307307
}
308308

309+
/// Note that a `BinaryHeap` is used for the remaining dependencies that need
310+
/// activation. This heap is sorted such that the "largest value" is the most
311+
/// constrained dependency, or the one with the least candidates.
312+
///
313+
/// This helps us get through super constrained portions of the dependency
314+
/// graph quickly and hopefully lock down what later larger dependencies can
315+
/// use (those with more candidates).
316+
#[derive(Clone)]
317+
pub struct RemainingDeps(BinaryHeap<DepsFrame>);
318+
319+
impl RemainingDeps {
320+
pub fn new() -> RemainingDeps {
321+
RemainingDeps(BinaryHeap::new())
322+
}
323+
pub fn push(&mut self, x: DepsFrame) {
324+
self.0.push(x)
325+
}
326+
pub fn pop_most_constrained(&mut self) -> Option<(bool, (Summary, (usize, DepInfo)))> {
327+
while let Some(mut deps_frame) = self.0.pop() {
328+
let just_here_for_the_error_messages = deps_frame.just_for_error_messages;
329+
330+
// Figure out what our next dependency to activate is, and if nothing is
331+
// listed then we're entirely done with this frame (yay!) and we can
332+
// move on to the next frame.
333+
if let Some(sibling) = deps_frame.remaining_siblings.next() {
334+
let parent = Summary::clone(&deps_frame.parent);
335+
self.0.push(deps_frame);
336+
return Some((just_here_for_the_error_messages, (parent, sibling)));
337+
}
338+
}
339+
None
340+
}
341+
pub fn iter(&mut self) -> impl Iterator<Item = (&PackageId, Dependency)> {
342+
self.0.iter().flat_map(|other| other.flatten())
343+
}
344+
}
345+
309346
// Information about the dependencies for a crate, a tuple of:
310347
//
311348
// (dependency info, candidates, features activated)

0 commit comments

Comments
 (0)