Skip to content

Commit

Permalink
run_graph: skip already executed tasks while walking the graph
Browse files Browse the repository at this point in the history
This has the nice side-effect of skipping the prepare step of crates
already fully tested.
  • Loading branch information
pietroalbini committed May 18, 2018
1 parent 64f7314 commit 8491c47
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 6 deletions.
28 changes: 22 additions & 6 deletions src/run_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,39 @@ impl TasksGraph {
id
}

pub fn next_task(&mut self) -> Option<(NodeIndex, Task)> {
pub fn next_task<DB: WriteResults>(
&mut self,
ex: &Experiment,
db: &DB,
) -> Option<(NodeIndex, Task)> {
let root = self.root;
if let WalkResult::Task(id, task) = self.walk_graph(root) {
if let WalkResult::Task(id, task) = self.walk_graph(root, ex, db) {
Some((id, task))
} else {
None
}
}

fn walk_graph(&mut self, node: NodeIndex) -> WalkResult {
fn walk_graph<DB: WriteResults>(
&mut self,
node: NodeIndex,
ex: &Experiment,
db: &DB,
) -> WalkResult {
// Ensure tasks are only executed if needed
if let Node::Task(ref task) = self.graph[node] {
if !task.needs_exec(ex, db) {
return WalkResult::NotBlocked;
}
}

let mut dependencies = 0;

// Try to check for the dependencies of this node
// The list is collected to make the borrowchecker happy
let mut neighbors = self.graph.neighbors(node).collect::<Vec<_>>();
for neighbor in neighbors.drain(..) {
match self.walk_graph(neighbor) {
match self.walk_graph(neighbor, ex, db) {
WalkResult::Task(id, task) => return WalkResult::Task(id, task),
WalkResult::Blocked => dependencies += 1,
WalkResult::NotBlocked => {}
Expand Down Expand Up @@ -197,7 +213,7 @@ pub fn run_ex<DB: WriteResults + Sync>(
let join = scope.builder().name(name).spawn(|| -> Result<()> {
// This uses a `loop` instead of a `while let` to avoid locking the graph too much
loop {
let option_task = graph.lock().unwrap().next_task();
let option_task = graph.lock().unwrap().next_task(ex, db);
if let Some((id, task)) = option_task {
info!("running task: {:?}", task);
task.run(ex, db)?;
Expand All @@ -221,7 +237,7 @@ pub fn run_ex<DB: WriteResults + Sync>(

// Only the root node must be present
let mut g = graph.lock().unwrap();
assert!(g.next_task().is_none());
assert!(g.next_task(ex, db).is_none());
assert_eq!(g.graph.neighbors(g.root).count(), 0);

Ok(())
Expand Down
14 changes: 14 additions & 0 deletions src/tasks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ impl fmt::Debug for Task {
}

impl Task {
pub fn needs_exec<DB: WriteResults>(&self, ex: &Experiment, db: &DB) -> bool {
// A prepare step should already be executed, and other steps only if were not executed
// already (on error checking if the step was executed it's executed again just to be safe)
match self.step {
TaskStep::Prepare => true,
TaskStep::BuildAndTest { ref tc, .. }
| TaskStep::BuildOnly { ref tc, .. }
| TaskStep::CheckOnly { ref tc, .. }
| TaskStep::UnstableFeatures { ref tc } => db.already_executed(ex, tc, &self.krate)
.unwrap_or(None)
.is_none(),
}
}

pub fn run<DB: WriteResults>(&self, ex: &Experiment, db: &DB) -> Result<()> {
match self.step {
TaskStep::Prepare => self.run_prepare(ex, db),
Expand Down

0 comments on commit 8491c47

Please sign in to comment.