Skip to content

Commit 9ef2958

Browse files
committed
sort the pending queue according to cost/priority
If multiple pieces of work are waiting in the pending queue, we can sort it according to their priorities: higher priorities should be scheduled sooner. They are more often than not wider than pure chains, and this should create more parallelism opportunities earlier in the pipeline: a high priority piece of work represents more future pieces of work down the line. This is a scheduling tradeoff that behaves differently for each project, machine configuration, amount of available parallelism at a given point in time, etc, but seems to help more often than hinders, at low-core counts and with enough units of work to be done, so that there is jobserver token contention where choosing a "better" piece of work to work on next is possible.
1 parent 646e9a0 commit 9ef2958

File tree

2 files changed

+16
-1
lines changed

2 files changed

+16
-1
lines changed

src/cargo/core/compiler/job_queue.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,11 +583,19 @@ impl<'cfg> DrainState<'cfg> {
583583
}
584584
}
585585

586+
// If multiple pieces of work are waiting in the pending queue, we can
587+
// sort it according to their priorities: higher priorities should be
588+
// scheduled sooner.
589+
self.pending_queue
590+
.sort_by_cached_key(|(unit, _)| self.queue.priority(unit));
591+
586592
// Now that we've learned of all possible work that we can execute
587593
// try to spawn it so long as we've got a jobserver token which says
588594
// we're able to perform some parallel work.
595+
// The `pending_queue` is sorted in ascending priority order, and we're
596+
// removing the highest priority items from its end.
589597
while self.has_extra_tokens() && !self.pending_queue.is_empty() {
590-
let (unit, job) = self.pending_queue.remove(0);
598+
let (unit, job) = self.pending_queue.pop().unwrap();
591599
*self.counts.get_mut(&unit.pkg.package_id()).unwrap() -= 1;
592600
if !cx.bcx.build_config.build_plan {
593601
// Print out some nice progress information.

src/cargo/util/dependency_queue.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,13 @@ impl<N: Hash + Eq + Clone, E: Eq + Hash + Clone, V> DependencyQueue<N, E, V> {
170170
self.dep_map.len()
171171
}
172172

173+
/// Returns the relative priority of a node. Higher priorities should be scheduled sooner.
174+
/// Currently computed as the transitive cost of the given node: its own, plus the cost of its
175+
/// reverse dependencies.
176+
pub(crate) fn priority(&self, node: &N) -> usize {
177+
self.priority[node]
178+
}
179+
173180
/// Indicate that something has finished.
174181
///
175182
/// Calling this function indicates that the `node` has produced `edge`. All

0 commit comments

Comments
 (0)