-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Async loading for outdir and proc-macro #7412
Conversation
11dc6c7
to
fe65078
Compare
Updated, use |
84b3929
to
b114f47
Compare
@@ -233,6 +233,70 @@ impl Server { | |||
}); | |||
self | |||
} | |||
|
|||
pub(crate) fn wait_until_workspace_and_build_data_are_loaded(self) -> Server { |
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.
The logic is quite complicated. But the problem here is our CI is not good on multi threading :( When priming caches, it eats a lot of cpu and coming requests will be too slow to run.
The second problem here is , the ordering of the "roots_scan" events are based on how threads are run, such that is indeterminate. We tried out best here to guess when the actual "roots scan" ends (And we will have 2 roots scan event 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.
For cache priming, I think we might want to just disable it for tests?
For the second issue, I think this logic belongs to the main loop. Specifically (and not only in tests), rust-analyzer should be able to tell the clients: "the project is fully loaded and I can serve every request".
We generally use the status
field to track this event:
And we communicate this to client via the status notification:
I am not sure why we even use progress rathe than status in support, I am trying to fix this right now.
For this PR,I think we want to change the status logic to only become ready once external resources are loaded
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 am trying to fix this right now.
Hm, this is for some reason more complicated that I expect. For some reason, multitheraded tests are really slow even with --release...
Finally took a look here! I think this is right in general terms, but there are a couple of concurrency-related things which make my old scars tingle :-) First, I am unsure about
This happens in the background thread which fetches the workspace. This I think The second thing I think can cause pain is this mutation
Fundamentally, what we have here are two source of information: workspace and build info. The current code merges them by destructively updating the state. This is a lossy operation, which can not be trivially undone. I think we can do the following:
Loading ws will set the first field, loading ws data will set the second one. When either of fields changes, we call |
51faee2
to
79c34e0
Compare
Fixed and sorry for the larger change set of this PR. It is due to the fact that I have to decouple the build data related config out of |
a257b1f
to
c01da06
Compare
pub(crate) build_data_loader: Option<BuildDataCollector>, | ||
pub(crate) fetch_build_data_queue: OpQueue, |
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.
The loader
field feels like it wants to be a part of OpQueue
:
//! Bookkeeping to make sure only one long-running operation is executed.
#[derive(Default)]
pub(crate) struct OpQueue<D> {
op_scheduled: Option<D>,
op_in_progress: bool,
}
impl<D> OpQueue<D> {
pub(crate) fn request_op(&mut self, data: D) {
self.op_scheduled = Some(data);
}
pub(crate) fn should_start_op(&mut self) -> Option<D> {
if self.op_in_progress {
return None;
}
self.op_in_progress = self.op_scheduled.is_some();
self.op_scheduled.take()
}
pub(crate) fn op_completed(&mut self) {
assert!(self.op_in_progress);
self.op_in_progress = false;
}
}
@@ -233,6 +233,70 @@ impl Server { | |||
}); | |||
self | |||
} | |||
|
|||
pub(crate) fn wait_until_workspace_and_build_data_are_loaded(self) -> Server { |
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.
For cache priming, I think we might want to just disable it for tests?
For the second issue, I think this logic belongs to the main loop. Specifically (and not only in tests), rust-analyzer should be able to tell the clients: "the project is fully loaded and I can serve every request".
We generally use the status
field to track this event:
And we communicate this to client via the status notification:
I am not sure why we even use progress rathe than status in support, I am trying to fix this right now.
For this PR,I think we want to change the status logic to only become ready once external resources are loaded
One of the problem here is, the So do you want me to do something like this ? : vfs::loader::Message::Progress { n_total, n_done } => {
if n_total == 0 {
self.transition(Status::Invalid);
} else {
let state = if n_done == 0 {
self.transition(Status::Loading);
Progress::Begin
} else if n_done < n_total {
Progress::Report
} else {
assert_eq!(n_done, n_total);
if self.config.load_out_dirs_from_check() {
if self.workspace_build_data.is_some() {
self.transition(Status::Ready);
}
} else {
self.transition(Status::Ready);
}
Progress::End
};
self.report_progress(
"roots scanned",
state,
Some(format!("{}/{}", n_done, n_total)),
Some(Progress::fraction(n_done, n_total)),
)
}
} |
Oh, but if we don't do cache priming, will the first request get longer to complete ? |
for tests, I would expect the opposite, as we'll be doing only necessary work.
Yeah, the specific transition rules (and the actual states we have) are tricky. I think we might want to split |
267e8b6
to
d22d20e
Compare
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.
left a couple of nits, but, other that that, r=me
d22d20e
to
edcafe7
Compare
And I removed the special case |
bors r=@maklad |
cc #7328
[Edit]
Finding a way to know when the workspace and build data are loaded...[Edit 2]
Not perfect solution, but seem to work now.