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

Make queries thread safe #49045

Merged
merged 2 commits into from
Apr 5, 2018
Merged

Make queries thread safe #49045

merged 2 commits into from
Apr 5, 2018

Conversation

Zoxc
Copy link
Contributor

@Zoxc Zoxc commented Mar 15, 2018

This makes queries thread safe by removing the query stack and making queries point to their parents. Queries write to the query map when starting and cycles are detected by checking if there's already an entry in the query map. This makes cycle detection O(1) instead of O(n), where n is the size of the query stack.

This is mostly corresponds to the method I described here.

cc @rust-lang/compiler

r? @michaelwoerister

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 15, 2018
@Zoxc Zoxc force-pushed the tls branch 2 times, most recently from 1836db4 to 61b5c59 Compare March 15, 2018 16:45
let job = if let Some(job) = job {
job
} else {
break lock;
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason why this line is not just return Ok(lock);? I think that would be clearer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that would be better. The break is there because this used to be part of another function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've fixed this.

Copy link
Member

Choose a reason for hiding this comment

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

👍

@Zoxc Zoxc force-pushed the tls branch 2 times, most recently from 37bb29d to 31c0581 Compare March 15, 2018 23:48
@pietroalbini
Copy link
Member

Ping from triage @michaelwoerister! The PR author pushed new commits, could you review them?

@michaelwoerister
Copy link
Member

I haven't forgotten about this, I'm just busy with bug fixing the last few days.

@nikomatsakis
Copy link
Contributor

Same here. I have some time scheduled for review later today, though I expect i'm largely going to defer to @michaelwoerister and/or @eddyb here since I don't have a ton of time right now.

Copy link
Contributor

@nikomatsakis nikomatsakis left a comment

Choose a reason for hiding this comment

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

Epic PR @Zoxc =)

I did a first read. I'm basically happy for now with the overall setup, which is what I expected. One obvious problem is that the code could use a lot more comments.

This is to some extent a pre-existing problem: the whole query setup is woefully underdocumented as is, but this is as good a time as any to fix that. In general, we should aim to make this stuff maximally readable.

(Once this has landed, I would like to iterate on some of the details, such as whether to use lazy or eager cycle detection, and the best way to handle blocking jobs -- but that can wait.)

use rustc_data_structures::sync::Lrc;

#[derive(Clone)]
pub struct ImplicitCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Needs documentation. What is an ImplicitCtxt?

@@ -1484,11 +1486,25 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {

impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> {
/// Call the closure with a local `TyCtxt` using the given arena.
pub fn enter_local<F, R>(&self, arena: &'tcx DroplessArena, f: F) -> R
pub fn enter_local<F, R>(&self,
Copy link
Contributor

Choose a reason for hiding this comment

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

If we're going to reformat, let's adopt the modern style:

pub fn enter_local<F, R>(
    &self,
    arena: &'tcx DroplessArena,
    f: F,
) -> R
where
    F: ...
{

})
}

pub fn with_thread_locals<F, R>(f: F) -> R
Copy link
Contributor

Choose a reason for hiding this comment

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

Comment please. (I know... the original code isn't that documented either...c'est la vie)

})
}

pub fn enter_context<'a, 'gcx: 'tcx, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'gcx, 'tcx>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: as above, let's adopt the modern style

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, comment =)

One thing I am wondering about: why does this take an &ImplicitCtxt versus creating one locally?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Typically you'd get the current ImplicitCtxt make a copy which changes a single field (queries modify the query field only, creating an new interner would modify tcx). Then you'd use enter_context to use this new ImplicitCtxt. We don't need to take ownership of the ImplicitCtxt so we pass it by reference.

}
}

pub fn with_fully_related_context<'a, 'gcx, 'tcx, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx>, f: F) -> R
Copy link
Contributor

Choose a reason for hiding this comment

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

Comment: what is a "fully related" context?

}

impl<'tcx> QueryJob<'tcx> {
pub fn new(entry: StackEntry<'tcx>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you please run rustfmt on this file? <3

@@ -389,7 +393,7 @@ define_maps! { <'tcx>
[] fn normalize_projection_ty: NormalizeProjectionTy(
CanonicalProjectionGoal<'tcx>
) -> Result<
Lrc<Canonical<'tcx, QueryResult<'tcx, NormalizationResult<'tcx>>>>,
Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, NormalizationResult<'tcx>>>>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm. We should probably rename canonical::QueryResult, but not in this PR.

fn try_get_lock(tcx: TyCtxt<'a, $tcx, 'lcx>,
mut span: Span,
key: &$K)
-> Result<LockGuard<'a, QueryMap<$tcx, Self>>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we make a custom enum here? This type is sort of incomprehensible. Something with named variants seems better. Like:

enum TryGetLock {
    NotYetStarted(Guard), // Today: Ok(guard)
    JobCompleted(...), // Today: Err(Ok(...))
    CycleDetected(...), // Today: Err(Err...))
}

I guess it means:

  • Ok(guard) -- no job yet started, lock is still held
  • Err(Ok(...)) -- cache hit, or else we blocked on a job and it completed
  • Err(Err(..)) -- cycle detected

profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
tcx.dep_graph.read_index(value.index);
return Ok((&value.value).clone());
macro_rules! get_lock {
Copy link
Contributor

Choose a reason for hiding this comment

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

why is this a macro and not a function?

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, because it returns I guess? Hmm. OK. Maybe we can rename it get_lock_or_return or something.

// Also signal the completion of the job, so waiters
// will continue execution
job.signal_complete();
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Neat.

@pietroalbini pietroalbini 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 Mar 20, 2018
@Zoxc
Copy link
Contributor Author

Zoxc commented Mar 21, 2018

@bors try

1 similar comment
@Zoxc
Copy link
Contributor Author

Zoxc commented Mar 21, 2018

@bors try

@bors
Copy link
Contributor

bors commented Mar 21, 2018

⌛ Trying commit 31c0581aa0a405f94d031f8570ba2f2938ccf2d1 with merge c83390e645c0ae1d55d6f56636824a76fe084663...

@bors
Copy link
Contributor

bors commented Mar 21, 2018

☀️ Test successful - status-travis
State: approved= try=True

@Zoxc
Copy link
Contributor Author

Zoxc commented Mar 21, 2018

@Mark-Simulacrum Can I get a perf run?

@Mark-Simulacrum
Copy link
Member

Perf queued.

@Zoxc Zoxc force-pushed the tls branch 2 times, most recently from bc428e1 to fa563bd Compare March 24, 2018 05:57
@Zoxc
Copy link
Contributor Author

Zoxc commented Mar 24, 2018

I've renamed StackEntry to QueryInfo since there's no longer a stack. I removed the track_diagnostics field of QueryJob since it was no longer used. I also added some comments.

@michaelwoerister
Copy link
Member

Sorry for not getting to this yet, @Zoxc. Either we'll take a look at this together during the work week or I'll do an in-depth review on Tuesday after Easter.

@shepmaster shepmaster 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 Mar 30, 2018
@michaelwoerister
Copy link
Member

OK, I finally had time to review this. The comments you added since the initial version make things a lot clearer, thanks, @Zoxc! I think we can go ahead an merge this. The basic strategy seems sound to me and a good starting point.

@nikomatsakis, are you satisfied with the comments added or do you want more? Otherwise, r=me.

@michaelwoerister
Copy link
Member

I'm going to go ahead and r+ this for now. We can always add more comments later.

@bors r+

@bors
Copy link
Contributor

bors commented Apr 5, 2018

📌 Commit 4f7d0fd has been approved by michaelwoerister

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 5, 2018
alexcrichton added a commit to alexcrichton/rust that referenced this pull request Apr 5, 2018
Make queries thread safe

This makes queries thread safe by removing the query stack and making queries point to their parents. Queries write to the query map when starting and cycles are detected by checking if there's already an entry in the query map. This makes cycle detection O(1) instead of O(n), where `n` is the size of the query stack.

This is mostly corresponds to the method I described [here](https://internals.rust-lang.org/t/parallelizing-rustc-using-rayon/6606).

cc @rust-lang/compiler

r? @michaelwoerister
@bors
Copy link
Contributor

bors commented Apr 5, 2018

⌛ Testing commit 4f7d0fd with merge 7222241...

bors added a commit that referenced this pull request Apr 5, 2018
Make queries thread safe

This makes queries thread safe by removing the query stack and making queries point to their parents. Queries write to the query map when starting and cycles are detected by checking if there's already an entry in the query map. This makes cycle detection O(1) instead of O(n), where `n` is the size of the query stack.

This is mostly corresponds to the method I described [here](https://internals.rust-lang.org/t/parallelizing-rustc-using-rayon/6606).

cc @rust-lang/compiler

r? @michaelwoerister
@bors
Copy link
Contributor

bors commented Apr 5, 2018

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

@bors bors merged commit 4f7d0fd into rust-lang:master Apr 5, 2018
bors added a commit that referenced this pull request Apr 5, 2018
Rollup of 8 pull requests

Successful merges:

 - #49045 (Make queries thread safe)
 - #49350 (Expand macros in `extern {}` blocks)
 - #49497 (Chalkify - Tweak `Clause` definition and HRTBs)
 - #49597 (proc_macro: Reorganize public API)
 - #49686 (typos)
- #49621
- #49697
- #49705

Failed merges:
@michaelwoerister
Copy link
Member

🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants