Skip to content
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

Loading the dependency graph in the background #46560

Merged
merged 2 commits into from
Dec 16, 2017
Merged

Conversation

Yoric
Copy link
Contributor

@Yoric Yoric commented Dec 7, 2017

Patch is a bit longer than I expected, due to the fact that most of this code relies upon a Session value, which is not Sync.

@rust-highfive
Copy link
Collaborator

r? @michaelwoerister

(rust_highfive has picked a reviewer for you, use r? to override)

@kennytm kennytm added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Dec 7, 2017

if self.cleanup_needed {
if let Err(err) = delete_all_session_dir_contents(sess) {
sess.err(&format!("Failed to delete invalidated or incompatible incremental compilation session \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tidy error.

[00:04:24] tidy error: /checkout/src/librustc_incremental/persist/load.rs:95: line longer than 100 chars

@@ -60,7 +59,7 @@ pub fn write_file_header<W: io::Write>(stream: &mut W) -> io::Result<()> {
/// incompatible version of the compiler.
/// - Returns `Err(..)` if some kind of IO error occurred while reading the
/// file.
pub fn read_file(sess: &Session, path: &Path) -> io::Result<Option<(Vec<u8>, usize)>> {
pub fn read_file(report_incremental_info: bool, path: &Path) -> io::Result<Option<(Vec<u8>, usize)>> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tidy error.

[00:04:24] tidy error: /checkout/src/librustc_incremental/persist/file_format.rs:62: line longer than 100 chars

Copy link
Member

@michaelwoerister michaelwoerister left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your PR, @Yoric!

I've left some comments below. I think the story around LoadResult is not factored quite cleanly yet.

let prev_dep_graph = time(time_passes, "load prev dep-graph", || {
// If necessary, compute the dependency graph (in the background).
let future_dep_graph = if sess.opts.build_dep_graph() {
Some(time(time_passes, "load prev dep-graph", || {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This time() call will only measure spawning the thread. I think it would make more sense to measure the duration spent in the new thread.

pub struct LoadResult<T> {
data: T,
cleanup_needed: bool,
warnings: Option<String>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are calling Session::err() with these, errors would be a better name (warning implies something non-fatal while error will abort the compilation process.

match file_format::read_file(report_incremental_info, path) {
Ok(Some(data_and_pos)) => LoadResult {
data: Some(data_and_pos),
..LoadResult::default()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I usually prefer listing fields exhaustively in situations like this, as it makes the code easier to read.

Ok(None) => {
// The file either didn't exist or was produced by an incompatible
// compiler version. Neither is an error.
LoadResult::default()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cleanup_needed must be set to true here (only the Ok(Some(..)) branch returned without the cleanup).

fn load_data(sess: &Session, path: &Path) -> Option<(Vec<u8>, usize)> {
match file_format::read_file(sess, path) {
Ok(Some(data_and_pos)) => return Some(data_and_pos),
pub struct LoadResult<T> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this should be an enum. Something like:

enum LoadResult {
    Ok { data: T },
    DataOutOfDate,
    Error { message: String },
}

if sess.opts.incremental.is_none() {
return empty
}
let aux = move || {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you make this just one closure that is directly passed to thread::spawn()? Having one closure nested inside of another feels a bit roundabout.

@carols10cents carols10cents added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 12, 2017
@Yoric
Copy link
Contributor Author

Yoric commented Dec 12, 2017

(updated)

@Yoric Yoric force-pushed the incr branch 2 times, most recently from e3a6b96 to 2130e5e Compare December 13, 2017 19:40
@Yoric
Copy link
Contributor Author

Yoric commented Dec 14, 2017

I don't really understand the tests that fail :/

@kennytm kennytm added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 14, 2017
@michaelwoerister
Copy link
Member

These tests make sure that some expected paths in the dep-graph exist and that others don't. That all the output is missing makes me suspect that the graph is not loaded at all or not generated.

Copy link
Member

@michaelwoerister michaelwoerister left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! This looks much cleaner now.

I think the failing tests are because the compiler crashes because we enable the dependency graph in these cases but don't specify a cache directory. This case was previously covered by 2130e5e#diff-8f003505e6f30ad2197a2883c43cb5c2L109.

To verify this, I'll run the tests locally and look at the actual test output (which can be found in text files within the build directory).

pub fn open(self, sess: &Session) -> PreviousDepGraph {
match self {
LoadResult::Error { message } => {
sess.err(&message) /* never returns */;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sess.err() actually does return (the compilation process is aborted at a later time, possible after more errors have been reported). But you can just use sess.fatal() to get the desired effect.

},
LoadResult::DataOutOfDate => {
if let Err(err) = delete_all_session_dir_contents(sess) {
sess.err(&format!("Failed to delete invalidated or incompatible \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also use sess.fatal() here too.

{
let is_incremental = sess.opts.incremental.is_some();
let report_incremental_info = sess.opts.debugging_opts.incremental_info;
let path = dep_graph_path_from(&sess.incr_comp_session_dir());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line might be crashing if the dependency graph is enabled but we don't have a caching directory. This can happen in the failing test cases. I'll verify this later.

@michaelwoerister
Copy link
Member

It looks like 2130e5e#diff-8f003505e6f30ad2197a2883c43cb5c2R140 really is the problem. Session::incr_comp_session_dir() must not be called if is_incremental is false. The API around this can probably be made nicer, but that's for another PR.

@Yoric Yoric force-pushed the incr branch 2 times, most recently from 7d3c8f2 to 67a085c Compare December 15, 2017 16:55
@Yoric
Copy link
Contributor Author

Yoric commented Dec 15, 2017

Ok, tests now pass :)

@michaelwoerister
Copy link
Member

Thanks a lot, @Yoric!

@bors r+

@bors
Copy link
Contributor

bors commented Dec 15, 2017

📌 Commit a0fb93d has been approved by michaelwoerister

@bors
Copy link
Contributor

bors commented Dec 15, 2017

⌛ Testing commit a0fb93d with merge cfd66a768a71a322d1d0e0ffc6116db5ad4b3b33...

@arielb1
Copy link
Contributor

arielb1 commented Dec 15, 2017

@bors retry

Prioritizing #45525

@bors
Copy link
Contributor

bors commented Dec 16, 2017

⌛ Testing commit a0fb93d with merge b3392f8...

bors added a commit that referenced this pull request Dec 16, 2017
Loading the dependency graph in the background

Patch is a bit longer than I expected, due to the fact that most of this code relies upon a `Session` value, which is not `Sync`.
@bors
Copy link
Contributor

bors commented Dec 16, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: michaelwoerister
Pushing b3392f8 to master...

@bors bors merged commit a0fb93d into rust-lang:master Dec 16, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants