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 const decoding thread-safe. #51060

Merged
merged 4 commits into from
Jun 1, 2018

Conversation

michaelwoerister
Copy link
Member

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

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 25, 2018
@bors
Copy link
Contributor

bors commented May 25, 2018

☔ The latest upstream changes (presumably #50967) made this pull request unmergeable. Please resolve the merge conflicts.

Copy link
Contributor

@oli-obk oli-obk left a comment

Choose a reason for hiding this comment

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

I like it!

// Don't recurse.
return Ok(alloc_id);
} else {
// Just spin. We could also decode concurrently.
Copy link
Contributor

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

Copy link
Member Author

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.

enum State {
Empty,
InProgress(DecodingSessionId, AllocId),
Done(AllocId),
Copy link
Contributor

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

Copy link
Member Author

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.


match alloc {
Ok(alloc) => {
decoder.tcx().alloc_map.lock().set_id_alloc(alloc_id, alloc);
Copy link
Contributor

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.

Copy link
Contributor

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?

Copy link
Member Author

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.

Copy link
Contributor

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.

Copy link
Member Author

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.

Copy link
Contributor

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.

Copy link
Member Author

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!

@michaelwoerister
Copy link
Member Author

I think, I'll go with the set_id_same_memory() approach for now. It's simpler.

@michaelwoerister
Copy link
Member Author

Oh wait, it's not really simpler. Now we have to keep track of multiple decoding sessions...

@michaelwoerister michaelwoerister force-pushed the thread-safe-consts branch 2 times, most recently from 482bbf3 to ee16739 Compare May 28, 2018 15:53
@michaelwoerister
Copy link
Member Author

Huh, it looks like we create a new interpret_alloc_cache and interpret_alloc_index every time something is decoded from metadata. That doesn't sound right :D

Some(alloc_id)
},
AllocKind::Fn | AllocKind::Static => {
// Fns and statics can be cyclic and their AllocId
Copy link
Contributor

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?

Copy link
Member Author

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"

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-3.9 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
[00:50:20] ................................................................i...................................
[00:50:25] ....................................................................................................
[00:50:31] ....................................................................................................
[00:50:38] .............................................................................................i......
[00:50:41] ...........iiiiiiiii...................................................
[00:50:41] 
[00:50:41] travis_fold:start:test_ui_nll
travis_time:start:test_ui_nll
Check compiletest suite=ui mode=ui compare_mode=nll (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
---
[00:51:30] ................................................................i...................................
[00:51:34] ....................................................................................................
[00:51:40] ....................................................................................................
[00:51:46] .............................................................................................i......
[00:51:48] ...........iiiiiiiii...................................................
[00:51:48] 
[00:51:48]  finished in 67.856
[00:51:48] travis_fold:end:test_ui_nll

---
[01:27:22]    Compiling rustc_data_structures v0.0.0 (file:///checkout/src/librustc_data_structures)
[01:27:25] error[E0308]: mismatched types
[01:27:25]    --> librustc_data_structures/tiny_list.rs:177:36
[01:27:25]     |
[01:27:25] 177 |             assert!(!list.contains(i));
[01:27:25]     |                                    |
[01:27:25]     |                                    expected &u32, found u32
[01:27:25]     |                                    help: consider borrowing here: `&i`
[01:27:25]     |
---
[01:27:25] 
[01:27:25] To learn more, run the command again with --verbose.
[01:27:25] 
[01:27:25] 
[01:27:25] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "test" "--target" "x86_64-unknown-linux-gnu" "-j" "4" "--release" "--locked" "--color" "always" "--features" " jemalloc" "--manifest-path" "/checkout/src/rustc/Cargo.toml" "-p" "rustc_data_structures" "--" "--quiet"
[01:27:25] 
[01:27:25] 
[01:27:25] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[01:27:25] Build completed unsuccessfully in 0:39:32
[01:27:25] Build completed unsuccessfully in 0:39:32
[01:27:25] make: *** [check] Error 1
[01:27:25] Makefile:58: recipe for target 'check' failed

The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:06d52276
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)

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 @TimNN. (Feature Requests)

@bors
Copy link
Contributor

bors commented May 29, 2018

☔ 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>>,
Copy link
Member Author

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.

@michaelwoerister
Copy link
Member Author

Let's see if this changes performance. The metadata caching issue is fixed but the index of allocations is loaded eagerly now.

@bors try

@bors
Copy link
Contributor

bors commented May 29, 2018

⌛ Trying commit 233c00c with merge cd7eecf...

bors added a commit that referenced this pull request May 29, 2018
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
@michaelwoerister michaelwoerister changed the title WIP: Make const decoding thread-safe. Make const decoding thread-safe. May 29, 2018
@michaelwoerister
Copy link
Member Author

Otherwise this should be ready for review, @Zoxc.

@bors
Copy link
Contributor

bors commented May 29, 2018

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

@michaelwoerister
Copy link
Member Author

@Mark-Simulacrum, could we get a perf run here please?

@michaelwoerister
Copy link
Member Author

@Zoxc & @oli-obk, do you think we should use spinning instead of racing? I don't really care, it's your call.

@oli-obk
Copy link
Contributor

oli-obk commented May 29, 2018

No opinion as long as we always have the plan to use work stealing at some point

@michaelwoerister
Copy link
Member Author

@Mark-Simulacrum
Copy link
Member

I've queued per

@michaelwoerister
Copy link
Member Author

Thanks, @Mark-Simulacrum!

@michaelwoerister
Copy link
Member Author

Performance looks OK.

@Zoxc
Copy link
Contributor

Zoxc commented May 31, 2018

@bors r+

@bors
Copy link
Contributor

bors commented May 31, 2018

📌 Commit 233c00c has been approved by Zoxc

@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 May 31, 2018
@michaelwoerister
Copy link
Member Author

Thanks for the review!

@bors
Copy link
Contributor

bors commented May 31, 2018

🔒 Merge conflict

@bors bors 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-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels May 31, 2018
@michaelwoerister
Copy link
Member Author

Rebased.

@bors r=Zoxc

@bors
Copy link
Contributor

bors commented Jun 1, 2018

📌 Commit 12e8359 has been approved by Zoxc

@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-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jun 1, 2018
@bors
Copy link
Contributor

bors commented Jun 1, 2018

⌛ Testing commit 12e8359 with merge 4412902...

bors added a commit that referenced this pull request Jun 1, 2018
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
@bors
Copy link
Contributor

bors commented Jun 1, 2018

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

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.

6 participants