-
-
Notifications
You must be signed in to change notification settings - Fork 628
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nhoward/rust graph validation pt i #4227
Nhoward/rust graph validation pt i #4227
Conversation
The current graph validation is written in Python. This begins to port it to rust by introducing the basic structure needed. It's still pretty rough. I've included a number of elements that are not yet used which could be removed for this iteration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Nick!
@@ -149,6 +149,8 @@ | |||
ExecutionStat execution_execute(RawScheduler*); | |||
RawNodes* execution_roots(RawScheduler*); | |||
|
|||
void run_validator(RawScheduler*, TypeId*, uint64_t); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming nit... the methods are mostly namespaced. So maybe validator_run
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
handled.
src/rust/engine/src/graph.rs
Outdated
@@ -213,6 +216,7 @@ impl Graph { | |||
let src = self.entry_for_id(src_id); | |||
dsts.into_iter() | |||
.filter(|dst_id| !(src.dependencies.contains(dst_id) || src.cyclic_dependencies.contains(dst_id))) | |||
// RGTODO add filter that removes deps if they will noop based on their rule edges |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that this will obviously be part of phase 2/3, but it's not clear that this is where it would happen, so the todo is probably misplaced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed.
src/rust/engine/src/rule_graph.rs
Outdated
|
||
// I think I ought to be able to replace the below with a set of structs keyed by EntryType. | ||
// My first couple attempts failed. | ||
#[derive(Eq, Hash, PartialEq, Clone, Debug)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this struct is probably 1 byte wide, just marking it Copy
rather than Clone
would be perfectly reasonable, and allow you to avoid explicitly calling clone in a bunch of places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(...and ignore this if you end up going the "one big enum" route.)
src/rust/engine/src/rule_graph.rs
Outdated
entry_type: EntryType::Unreachable, | ||
subject_type: None, | ||
value: None, | ||
rule: Some(rule.clone()), // TODO decide on clone vs lifetimes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd stick with cloning for now. Can revisit later if it's an issue, but it seems unlikely to be.
src/rust/engine/src/rule_graph.rs
Outdated
selector: None, | ||
reason: None, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing whitespace
src/rust/engine/src/tasks.rs
Outdated
@@ -8,9 +8,13 @@ use selectors::{Selector, Select, SelectDependencies, SelectLiteral, SelectProje | |||
* Registry of tasks able to produce each type, along with a few fundamental python | |||
* types that the engine must be aware of. | |||
*/ | |||
#[derive(Clone)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you open a github issue about removing Clone
here? It's a bit error prone, because the tasks get passed around everywhere currently, and cloning them accidentally (probably in a parent struct) would get costly fast.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. #4236
self.all_rules().iter().map(|t| t.product).collect() | ||
} | ||
|
||
pub fn is_singleton_task(&self, sought_task: &Task) -> bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth adding a Singleton/Intrinisic/Normal
enum on Task
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm. that would certainly simplify these. I think I'd want to split that out as a separate change though. Sound reasonable?
src/rust/engine/src/tasks.rs
Outdated
} | ||
|
||
pub fn all_rules(&self) -> Vec<Task> { | ||
let mut result: Vec<Task> = Vec::new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another way to accomplish method would be:
let rules: Vec<_> = self.tasks.values().chain(self.singletons.values()).chain(self.singletons.values()).collect();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
neat. I had to add a flat_map, but that's much more concise without losing readability.
src/rust/engine/src/rule_graph.rs
Outdated
let rules_in_graph: HashSet<Task> = full_dependency_edges.keys().map(|f| f.rule().clone()).collect(); | ||
let unfulfillable_discovered_during_construction: HashSet<Task> = full_unfulfillable_rules.keys().map(|f| f.rule().clone()).collect(); | ||
let declared_rules = self.tasks.all_rules(); | ||
let unreachable_rules: HashSet<&Task> = declared_rules.iter() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that when the type annotation is use to guide inference for collect
, it isn't necessary to actually fill in its parameters:
let unreachable_rules: HashSet<_> = declared_rules.iter()...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, so it's like the diamond operator in Java. Also neat. Is doing it that way preferred over the turbo fish? ie let foo = ...collect::<Vec<_>>()
src/rust/engine/src/rule_graph.rs
Outdated
.filter(|g| !root_rule_dependency_edges.contains_key(g)) | ||
.map(|g| g.clone()); | ||
for unseen_rule in unseen_dep_rules { | ||
rules_to_traverse.push_back(unseen_rule); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can use extend
here, which consumes an iterator.
rules_to_traverse.extend(unseen_dep_rules);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think my only blocker for landing this would be cleaning up the commented code a bit.
Tweaking the datamodel a bit would likely lay important groundwork too, but I won't block on it.
…o edge collections are properly typed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Nick!
src/rust/engine/src/graph.rs
Outdated
@@ -1,3 +1,5 @@ | |||
// Copyright 2016 Pants project contributors (see CONTRIBUTORS.md). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're going to add these, might as well go with the current year.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
roger
src/rust/engine/src/selectors.rs
Outdated
@@ -59,6 +59,9 @@ impl Selector { | |||
) | |||
} | |||
|
|||
/* | |||
* The product type this selector will ultimately produce. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know we're not really following rust style at all, but the indentation is funny here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah. I'll reformat to be at least Javaish
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. After thinking a bit, I looked at the Rust book again. It seems like line comments are preferred. And the doc comments are form of line comments. I'm changing it to line comments
https://doc.rust-lang.org/beta/book/comments.html
src/rust/engine/src/rule_graph.rs
Outdated
// I think I ought to be able to replace the below with a set of structs keyed by EntryType. | ||
// My first couple attempts failed. | ||
#[derive(Eq, Hash, PartialEq, Clone, Debug)] | ||
enum EntryType { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much better! It looks like is now just Entry
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call.
|
||
}, | ||
&Selector::Task(ref select) =>{ | ||
// TODO, not sure what task is in this context exactly |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's for symmetry: every Node
type has a Selector
currently. But probably possible to remove.
-- also removed the Clone on Tasks since an upstream change caused it to not be viable
src/rust/engine/src/tasks.rs
Outdated
@@ -8,9 +8,14 @@ use selectors::{Selector, Select, SelectDependencies, SelectLiteral, SelectProje | |||
* Registry of tasks able to produce each type, along with a few fundamental python | |||
* types that the engine must be aware of. | |||
*/ | |||
// TODO remove Clone https://github.com/pantsbuild/pants/issues/4236 | |||
#[derive(Clone)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the merge from master, I was forced to handle this. So it's gone. Closing the issue.
- fix year - s/EntryType/Entry/ - change comments - clarify panics in a few places
…ld#4227) This is the first step towards adapting the static noop culling I worked on last year to the Rust code base. This first patch is working towards replacing the graph validator written in python with one in rust. At this point it covers quite a lot of behavior, but it isn't working quite correctly yet. This patch includes porting the majority of the rule graph construction. Including - replacing the root selector fn dict with a set of subjects and a method. Since all of the subjects now use the same selector, it didn't make sense to keep. - running the rust validator, but ignoring the results. - adding copyright headers. rule_graph.rs is where the meat of the port is. There are still a number of unported sections. I'll be removing the commented python and replacing it with rust in subsequent pull requests The remaining portions are - adding a enum on tasks for their task type - removing unfulfillable entries from the graph - handling SelectDependencies / SelectProjection selectors - handling snapshots - propagating the results back to the python side
This is the first step towards adapting the static noop culling I worked on last year to the rust code.
This first patch is working towards replacing the graph validator written in python with one in rust. At this point it covers quite a lot of behavior, but it isn't working quite correctly yet.
I'm putting it up in the current state to get some other eyes on it while I iterate.
I'm hoping to have this initial patch wrapped up tomorrow, modulo bugs.
Things to look at: