-
Notifications
You must be signed in to change notification settings - Fork 966
Concurrently download components of a toolchain #4436
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
base: master
Are you sure you want to change the base?
Concurrently download components of a toolchain #4436
Conversation
3a7ac67
to
10d1514
Compare
Some notifications needed to be updated to include the download URL, enabling the identification of the component being downloaded. This was necessary for accurate progress reporting of each component.
10d1514
to
7093333
Compare
if let Some(pb) = self.find_progress_bar(file) { | ||
pb.set_style( | ||
ProgressStyle::with_template( | ||
"{msg:>12.bold} downloaded {total_bytes} in {elapsed}.", |
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.
Nit: .
should be omitted to be coherent with the general notification style.
self.progress_bar.set_length(content_len); | ||
self.progress_bar.set_style( | ||
/// Helper function to find the progress bar for a given file. | ||
fn find_progress_bar(&mut self, file: &str) -> Option<&mut ProgressBar> { |
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.
Nit: progress_bar()
would be a better name according to the API style guide.
.file_progress_bars | ||
.keys() | ||
.find(|comp| file.contains(*comp)) | ||
.cloned()?; |
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 should not be necessary to clone this component given that we will immediately refer to it.
.await; | ||
for result in results { | ||
match result { | ||
Ok((component, format, downloaded_file, hash)) => { |
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.
Nit: Isn't this just let (...) = result?;
?
.with_context(|| { | ||
RustupError::ComponentDownloadFailed(component.name(new_manifest)) | ||
})?; | ||
Ok::<(Component, CompressionKind, File, String), Error>(( |
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 this annotation be simpler, say Ok::<_, Error>
?
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 believe we can simply drop the annotation.
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.
As I was addressing the previous nit, I have came to the conclusion that this is necessary. Sorry for the confusion.
@@ -14,11 +14,11 @@ pub enum Notification<'a> { | |||
RemovingDirectory(&'a str, &'a Path), | |||
DownloadingFile(&'a Url, &'a Path), | |||
/// Received the Content-Length of the to-be downloaded data. | |||
DownloadContentLengthReceived(u64), | |||
DownloadContentLengthReceived(u64, &'a str), |
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.
Would you mind explaining the meaning of ""
here and why they are required? It might be an interesting addition to the doc comments as well.
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.
A note to myself: we also have to consider the restriction of concurrent downloads similar to what we have done with threadpooled diskio.
) | ||
.unwrap() | ||
.progress_chars("## "), | ||
); | ||
pb.set_message(component.to_string()); |
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.
Nit: .to_string()
doesn't seem necessary here...
As of now, each component of a toolchain is downloaded sequentially, leaving room for performance improvements.
This is particularly notorious when considering interleaving downloads with installation, as discussed in #731.
Following the work made in #4426, as the
DownloadTracker
is nowindicatif
-based, doing the progress reporting for concurrent downloads is much easier.As such, this PR comes to enable downloading different components concurrently (possibly closing #3018).
Performance-wise, benchmarks using
hyperfine
showed a small (1.1x) speedup -- which doesn't seem noticeable but lays the foundations for a future PR to interleave the download with the installation (of components).The benchmarks were ran 50 times (with 5 warmup runs) over a 50 Mbps connection, each downloading an entire toolchain.
Many thanks to @rami3l and his PR for refactoring part of the test suite for the purpose of this PR.