Skip to content

Commit 25bf99b

Browse files
Refactor to_send_clients to use a BTreeMap
This is both a performance optimization (avoiding O(n) shifting from the beginning), and communicates intent in a nicer way overall. It is plausible that we will eventually want to tie this data structure to something like the DependencyQueue, i.e., to get more information on which rustc to give tokens to. An old rustc with a very late dependency edge is less important than one we'll need sooner, probably.
1 parent 4bd074e commit 25bf99b

File tree

1 file changed

+27
-17
lines changed

1 file changed

+27
-17
lines changed

src/cargo/core/compiler/job_queue.rs

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
//! improved.
5151
5252
use std::cell::Cell;
53-
use std::collections::{HashMap, HashSet};
53+
use std::collections::{BTreeMap, HashMap, HashSet};
5454
use std::io;
5555
use std::marker;
5656
use std::mem;
@@ -119,11 +119,8 @@ struct DrainState<'a, 'cfg> {
119119
rustc_tokens: HashMap<JobId, Vec<Acquired>>,
120120

121121
/// This represents the list of rustc jobs (processes) and associated
122-
/// clients that are interested in receiving a token. Note that each process
123-
/// may be present many times (if it has requested multiple tokens).
124-
// We use a vec here as we don't want to order randomly which rustc we give
125-
// tokens to.
126-
to_send_clients: Vec<(JobId, Client)>,
122+
/// clients that are interested in receiving a token.
123+
to_send_clients: BTreeMap<JobId, Vec<Client>>,
127124

128125
/// The list of jobs that we have not yet started executing, but have
129126
/// retrieved from the `queue`. We eagerly pull jobs off the main queue to
@@ -135,7 +132,7 @@ struct DrainState<'a, 'cfg> {
135132
finished: usize,
136133
}
137134

138-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
135+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
139136
pub struct JobId(pub u32);
140137

141138
impl std::fmt::Display for JobId {
@@ -357,7 +354,7 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
357354

358355
tokens: Vec::new(),
359356
rustc_tokens: HashMap::new(),
360-
to_send_clients: Vec::new(),
357+
to_send_clients: BTreeMap::new(),
361358
pending_queue: Vec::new(),
362359
print: DiagnosticPrinter::new(cx.bcx.config),
363360
finished: 0,
@@ -428,11 +425,26 @@ impl<'a, 'cfg> DrainState<'a, 'cfg> {
428425
self.active.len() < self.tokens.len() + 1
429426
}
430427

428+
// The oldest job (i.e., least job ID) is the one we grant tokens to first.
429+
fn pop_waiting_client(&mut self) -> (JobId, Client) {
430+
// FIXME: replace this with BTreeMap::first_entry when that stabilizes.
431+
let key = *self
432+
.to_send_clients
433+
.keys()
434+
.next()
435+
.expect("at least one waiter");
436+
let clients = self.to_send_clients.get_mut(&key).unwrap();
437+
let client = clients.pop().unwrap();
438+
if clients.is_empty() {
439+
self.to_send_clients.remove(&key);
440+
}
441+
(key, client)
442+
}
443+
431444
// If we managed to acquire some extra tokens, send them off to a waiting rustc.
432445
fn grant_rustc_token_requests(&mut self) -> CargoResult<()> {
433446
while !self.to_send_clients.is_empty() && self.has_extra_tokens() {
434-
// Remove from the front so we grant the token to the oldest waiter
435-
let (id, client) = self.to_send_clients.remove(0);
447+
let (id, client) = self.pop_waiting_client();
436448
// This unwrap is guaranteed to succeed. `active` must be at least
437449
// length 1, as otherwise there can't be a client waiting to be sent
438450
// on, so tokens.len() must also be at least one.
@@ -494,12 +506,7 @@ impl<'a, 'cfg> DrainState<'a, 'cfg> {
494506
// completely.
495507
self.tokens.extend(rustc_tokens);
496508
}
497-
while let Some(pos) =
498-
self.to_send_clients.iter().position(|(i, _)| *i == id)
499-
{
500-
// drain all the pending clients
501-
self.to_send_clients.remove(pos);
502-
}
509+
self.to_send_clients.remove(&id);
503510
self.active.remove(&id).unwrap()
504511
}
505512
// ... otherwise if it hasn't finished we leave it
@@ -536,7 +543,10 @@ impl<'a, 'cfg> DrainState<'a, 'cfg> {
536543
Message::NeedsToken(id, client) => {
537544
log::info!("queue token request");
538545
jobserver_helper.request_token();
539-
self.to_send_clients.push((id, client));
546+
self.to_send_clients
547+
.entry(id)
548+
.or_insert_with(Vec::new)
549+
.push(client);
540550
}
541551
Message::ReleaseToken(id) => {
542552
// Note that this pops off potentially a completely

0 commit comments

Comments
 (0)