-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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 const decoding thread-safe. #51060
Conversation
☔ The latest upstream changes (presumably #50967) made this pull request unmergeable. Please resolve the merge conflicts. |
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 like it!
src/librustc/mir/interpret/mod.rs
Outdated
// Don't recurse. | ||
return Ok(alloc_id); | ||
} else { | ||
// Just spin. We could also decode concurrently. |
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.
ideally we'd turn this into a work stealing algo for allocations with loads of relocations... someday
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.
Yes, with Rayon it might not even be that hard.
src/librustc/mir/interpret/mod.rs
Outdated
enum State { | ||
Empty, | ||
InProgress(DecodingSessionId, AllocId), | ||
Done(AllocId), |
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.
If you made this store the Result instead of just the Ok value, you can get rid of the panicking and poisoning
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'll look into it.
src/librustc/mir/interpret/mod.rs
Outdated
|
||
match alloc { | ||
Ok(alloc) => { | ||
decoder.tcx().alloc_map.lock().set_id_alloc(alloc_id, alloc); |
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 should use the set_id_same_memory
function I introduced in my PR. AllocKind::Fn
and AllocKind::Static
should still use create_fn_alloc
and intern_static
.
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 instance decoding potentially be expensive? Or DefId decoding?
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 should use the set_id_same_memory function I introduced in my PR.
With the spinning solution (which again, I don't necessarily prefer) setting things in the alloc_map
is not racy, so asserting that no key existed should be correct (and avoids doing a comparison).
Can instance decoding potentially be expensive? Or DefId decoding?
It's not free. I think we should cache statics and fns too, if it doesn't complicate the algorithm.
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.
Yeah, you could just have a set_id_memory
which just asserts that there was no existing entry.
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 does that already, if I'm not mistaken.
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.
Your accepts AllocType
, which is incorrect, since AllocType::Function
and AllocType::Static
are interned. It should only accept allocations.
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'll look into that. Thanks for the hint!
I think, I'll go with the |
Oh wait, it's not really simpler. Now we have to keep track of multiple decoding sessions... |
482bbf3
to
ee16739
Compare
Huh, it looks like we create a new |
src/librustc/mir/interpret/mod.rs
Outdated
Some(alloc_id) | ||
}, | ||
AllocKind::Fn | AllocKind::Static => { | ||
// Fns and statics can be cyclic and their AllocId |
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.
How can they be cyclic?
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.
whoops, that should say "cannot be cyclic"
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
ee16739
to
1afcaf6
Compare
☔ The latest upstream changes (presumably #50475) made this pull request unmergeable. Please resolve the merge conflicts. |
|
||
pub struct AllocDecodingState { | ||
// For each AllocId we keep track of which decoding state it's currently in. | ||
decoding_state: Vec<Mutex<State>>, |
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.
Note that I changed this from Mutex<Vec<_>>
to Vec<Mutex<_>>
. In theory this should reduce contention but it might be overkill.
1afcaf6
to
233c00c
Compare
Let's see if this changes performance. The metadata caching issue is fixed but the index of allocations is loaded eagerly now. @bors try |
WIP: Make const decoding thread-safe. This is an alternative to #50957. It's a proof of concept (e.g. it doesn't adapt metadata decoding, just the incr. comp. cache) but I think it turned out nice. It's rather simple and does not require passing around a bunch of weird closures, like we currently do. If you (@Zoxc & @oli-obk) think this approach is good then I'm happy to finish and clean this up. Note: The current version just spins when it encounters an in-progress decoding. I don't have a strong preference for this approach. Decoding concurrently is equally fine by me (or maybe even better because it doesn't require poisoning). r? @Zoxc
Otherwise this should be ready for review, @Zoxc. |
☀️ Test successful - status-travis |
@Mark-Simulacrum, could we get a perf run here please? |
No opinion as long as we always have the plan to use work stealing at some point |
Here is the perf link: http://perf.rust-lang.org/compare.html?start=4f6d9bf2099c83f365bb0b3cf02091b4737c2052&end=cd7eecf54f05b3c5e0cf3797b5764cdb0bcd3972&stat=instructions%3Au But I don't think the perf run has been done yet (cc @Mark-Simulacrum) |
I've queued per |
Thanks, @Mark-Simulacrum! |
Performance looks OK. |
@bors r+ |
📌 Commit 233c00c has been approved by |
Thanks for the review! |
🔒 Merge conflict |
233c00c
to
12e8359
Compare
Rebased. @bors r=Zoxc |
📌 Commit 12e8359 has been approved by |
Make const decoding thread-safe. This is an alternative to #50957. It's a proof of concept (e.g. it doesn't adapt metadata decoding, just the incr. comp. cache) but I think it turned out nice. It's rather simple and does not require passing around a bunch of weird closures, like we currently do. If you (@Zoxc & @oli-obk) think this approach is good then I'm happy to finish and clean this up. Note: The current version just spins when it encounters an in-progress decoding. I don't have a strong preference for this approach. Decoding concurrently is equally fine by me (or maybe even better because it doesn't require poisoning). r? @Zoxc
☀️ Test successful - status-appveyor, status-travis |
This is an alternative to #50957. It's a proof of concept (e.g. it doesn't adapt metadata decoding, just the incr. comp. cache) but I think it turned out nice. It's rather simple and does not require passing around a bunch of weird closures, like we currently do.
If you (@Zoxc & @oli-obk) think this approach is good then I'm happy to finish and clean this up.
Note: The current version just spins when it encounters an in-progress decoding. I don't have a strong preference for this approach. Decoding concurrently is equally fine by me (or maybe even better because it doesn't require poisoning).
r? @Zoxc