Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upReplace LockCell with atomic types #56614
Conversation
rust-highfive
assigned
michaelwoerister
Dec 7, 2018
rust-highfive
added
the
S-waiting-on-review
label
Dec 7, 2018
michaelwoerister
reviewed
Dec 10, 2018
pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool { | ||
#[inline(never)] | ||
#[cold] | ||
pub fn consider_optimizing_cold<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool { |
This comment has been minimized.
This comment has been minimized.
michaelwoerister
Dec 10, 2018
Contributor
Does splitting this into two functions really translate to faster compile-times?
This comment has been minimized.
This comment has been minimized.
Zoxc
Dec 10, 2018
Author
Contributor
It is used in layout computation. Not sure how hot it is, but it probably won't hurt. Especially if we want to add more MIR optimizations (and debug them)
This comment has been minimized.
This comment has been minimized.
Zoxc
Dec 10, 2018
Author
Contributor
Anyway this PR is mostly about getting rid of LockCell
, I just found this on the way
This comment has been minimized.
This comment has been minimized.
michaelwoerister
Dec 10, 2018
Contributor
OK. It does hurt code quality though as it makes things more complicated and thus harder to read and maintain. I personally prefer not to do things like this without evidence that it carries it's weight.
This comment has been minimized.
This comment has been minimized.
@bors try |
This comment has been minimized.
This comment has been minimized.
added a commit
that referenced
this pull request
Dec 10, 2018
This comment has been minimized.
This comment has been minimized.
|
This comment has been minimized.
This comment has been minimized.
Just a suggestion: Instead of
|
whataloadofwhat
reviewed
Dec 11, 2018
let mut ret = true; | ||
if let Some(ref c) = self.optimization_fuel_crate { | ||
if c == crate_name { | ||
assert_eq!(self.query_threads(), 1); | ||
let fuel = self.optimization_fuel_limit.get(); | ||
let fuel = self.optimization_fuel_limit.load(SeqCst); |
This comment has been minimized.
This comment has been minimized.
whataloadofwhat
Dec 11, 2018
Contributor
This function is pretty racy I think.
This should all be in a cas loop and the other section (for print_fuel) should be a fetch add, right?
Granted it was racy before even with locks, but still.
This comment has been minimized.
This comment has been minimized.
michaelwoerister
Dec 11, 2018
Contributor
It asserts that the compiler is running in single-threaded mode, so it should be fine. It would be nicer though if the two fields in question would be behind a single lock.
This comment has been minimized.
This comment has been minimized.
@stjepang This looks great. Yes, that sounds like the way to go. We already have |
This comment has been minimized.
This comment has been minimized.
@rust-timer build bcc6e63 |
This comment has been minimized.
This comment has been minimized.
rust-timer
commented
Dec 11, 2018
Success: Queued bcc6e63 with parent 3a75e80, comparison URL. |
bot
added a commit
to crossbeam-rs/crossbeam
that referenced
this pull request
Dec 11, 2018
This comment has been minimized.
This comment has been minimized.
rust-timer
commented
Dec 11, 2018
Finished benchmarking try commit bcc6e63 |
This comment has been minimized.
This comment has been minimized.
The changes here don't seem to make much of a difference performance-wise. I'd say, as a consequence, we should optimize for code quality:
|
bot
added a commit
to crossbeam-rs/crossbeam
that referenced
this pull request
Dec 11, 2018
This comment has been minimized.
This comment has been minimized.
I've just put |
This comment has been minimized.
This comment has been minimized.
@stjepang The use of volatile reads doesn't inspire confidence. Some |
This comment has been minimized.
This comment has been minimized.
FWIW, @RalfJung has reviewed those volatile reads and written comments above them.
The code is parametrized over
Another benefit is that reads are very fast (faster than Additionally, if you don't need |
This comment has been minimized.
This comment has been minimized.
@stjepang Do you mean the comments in https://github.com/crossbeam-rs/crossbeam/pull/234/files? Those are different accesses though, are they not? The volatile accesses I looked at all have a comment saying "this is UB but we do it anyway because performance".^^ |
This comment has been minimized.
This comment has been minimized.
@RalfJung Sorry, my bad! I confused this volatile read with the CAS that issues a SeqCst fence. If you'd like to review this situation, though, that'd be great! :) We're using a volatile read to read a value that might be concurrently written to. However, we can detect when a data race happens by reading the sequence number. If the value was overwritten while we were reading it, then we try reading again in a loop. The Chase-Lev deque uses a very similar technique. If we wanted to be pedantic, we'd use multiple |
This comment has been minimized.
This comment has been minimized.
The main benefit I see is being able to remove |
This comment has been minimized.
This comment has been minimized.
This PR already does that and uses |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I didn't notice the lack of |
This comment has been minimized.
This comment has been minimized.
I depends. If I don't really need them (like in the cases modified in this PR), I prefer them not to be exposed in the interface. |
This comment has been minimized.
This comment has been minimized.
I would say yes.
Not only that, let a = AtomicCell::new(vec![]);
// Thread #1
a.store(vec![1, 2, 3], Relaxed);
// Thread #2
println!("{:?}", a.take(Relaxed)); // unsynchronized read! |
This comment has been minimized.
This comment has been minimized.
This sounds a lot like sequence locks to me, which are a notorious problem for language-level memory models. AFAIK, they cannot be implemented in C and hence not in Rust, either. So the reason you don't do a relaxed load is because this is arbitrarily-sized data? Following our own definitions, this is UB because of a read-write race. Following LLVM's definitions, the read is fine but returns However, given taht volatile loads cannot be duplicated, the If we keep wanting the LLVM memory model, maybe we should just change the documentation and say we are using the LLVM model? The relevant difference is that read-write races are not UB, they just return indeterminate data (which is the same as uninitialized data and padding bits). You are not allowed to do anything with that data, and you should probably wrap it in a For the LLVM side, can we at least get an LLVM developer on the record saying that volatile accesses never return Cc @rkruppe |
This comment has been minimized.
This comment has been minimized.
So which ordering does it use, always release/acquire? |
This comment has been minimized.
This comment has been minimized.
Yes, this is a sequence lock. We based our implementation on the paper you've linked.
Exactly.
Yeah, we don't use the data if a race happens (it's mem::forgotten). The Chase-Lev deque (
I was a big proponent of guaranteeing |
This comment has been minimized.
This comment has been minimized.
Ah I see, the data is literally not looked at at all if a race happened, and the detection happens through another channel. The The good news is that I think you don't even need a volatile read! You don't care if racy reads yield I suspect Rust picked the C11 model because it is much better studied, and that is still true. I know of hardly any academic work on memory models that are as permissive with read-write races as LLVM is. However, there is some very recent work that I should read that takes this into account.
No.
I think I took a look at the
A read in the fast case proceeds as
I just spent quite a while wondering about what the correctness argument here is, and why the fence is needed, and why the initial Generally, the library has way fewer comments than is adequate for such subtle concurrent data structures. In |
Zoxc
referenced this pull request
Dec 22, 2018
Merged
Optimize try_mark_green and eliminate the lock on dep node colors #57065
added a commit
that referenced
this pull request
Dec 22, 2018
Zoxc
added some commits
Dec 5, 2018
Zoxc
force-pushed the
Zoxc:query-perf2
branch
from
ed78d93
to
9b47acf
Dec 29, 2018
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
bors
added
S-waiting-on-bors
and removed
S-waiting-on-review
labels
Jan 9, 2019
This comment has been minimized.
This comment has been minimized.
added a commit
that referenced
this pull request
Jan 9, 2019
This comment has been minimized.
This comment has been minimized.
|
Zoxc commentedDec 7, 2018
Split from #56509
r? @michaelwoerister