-
Notifications
You must be signed in to change notification settings - Fork 251
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
perf: reduce peak memory usage and open files when loading bindle #440
Conversation
This reduces peak memory usage from ~200MB to |
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.
This looks great, and I learned a ton. Thank you! (The one suggestion is minor.)
crates/loader/src/bindle/assets.rs
Outdated
.await | ||
.with_context(|| anyhow!("Failed to fetch asset parcel '{}@{}'", self.id, p.sha256))?; | ||
|
||
let mut file = fs::File::create(&to).await?; |
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.
Could we add a with_context(...)
here so that the user can see where the failure was and which file/parcel it occurred on?
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 catch -- done.
Clippy also caught a bug, so I fixed that, too. Note to self: for x in stream.try_next().await? { .. }
almost certainly does not do what you want it to do.
This patch does two things: 1. Use `bindle::client::Client::get_parcel_stream` instead of `get_parcel`. The latter loads the whole asset into memory, while the former allows us to stream into a local file chunk-by-chunk. 2. Limit parallel I/O in `spin_loader::bindle::assets::Copier` to avoid hammering the Bindle server and also avoid running out of file descriptors. This addresses fermyon#413. Signed-off-by: Joel Dice <joel.dice@gmail.com>
.into_iter() | ||
.filter_map(|r| r.err()) | ||
match stream::iter(parcels.iter().map(|p| self.copy(p, &dir))) | ||
.buffer_unordered(MAX_PARALLEL_COPIES) |
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.
@adamreese I knew this was implemented somewhere!
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.
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.
This is great! Thank you!
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.
This is great, thank you so much!
Manually tested and profiled again, this is in line with what we are seeing when running Spin with local assets.
Thank you again, LGTM.
This patch does two things:
Use
bindle::client::Client::get_parcel_stream
instead ofget_parcel
. Thelatter loads the whole asset into memory, while the former allows us to stream
into a local file chunk-by-chunk.
Limit parallel I/O in
spin_loader::bindle::assets::Copier
to avoidhammering the Bindle server and also avoid running out of file descriptors.
This addresses #413.
Signed-off-by: Joel Dice joel.dice@gmail.com