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

Use the parking_lot locking primitives #56410

Closed
wants to merge 40 commits into from

Conversation

faern
Copy link
Contributor

@faern faern commented Dec 1, 2018

This PR adds the parking_lot code as a git submodule and reimplements all the standard library locking primitives so they are thin wrappers over the parking_lot equivalents. The standard library public API is of course kept the same.

This has been discussed in https://internals.rust-lang.org/t/standard-library-synchronization-primitives-and-undefined-behavior/8439/9

Thanks @Amanieu for mentoring when doing this, and basically all the code is his as well of course.

Fixes #35836
Fixes #53127

@rust-highfive

This comment has been minimized.

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

Centril commented Dec 1, 2018

r? @RalfJung

@Amanieu
Copy link
Member

Amanieu commented Dec 1, 2018

Just to be clear, this PR only changes the "back-end" of the mutex implementation. There are no changes to the public Mutex API in libstd. API changes (such as const fn support) can be done in a later PR.

@nagisa
Copy link
Member

nagisa commented Dec 1, 2018

There are no changes to the public Mutex API in libstd.

Isn’t there a difference between fairness of native Mutex and parking_lot’s Mutex?

EDIT: on some of the platforms, that is.

@Amanieu
Copy link
Member

Amanieu commented Dec 1, 2018

Isn’t there a difference between fairness of native Mutex and parking_lot’s Mutex?

Any fairness was "implementation-defined" in the current implementation.

Copy link
Contributor

@Centril Centril left a comment

Choose a reason for hiding this comment

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

Some observations; applies generally throughout the PR but I picked a few spots to illustrate. :)

src/libstd/sys_common/thread_parker.rs Outdated Show resolved Hide resolved
src/libstd/sys_common/thread_parker.rs Outdated Show resolved Hide resolved
src/libstd/sys_common/thread_parker.rs Outdated Show resolved Hide resolved
src/libstd/sys_common/parking_lot_core/word_lock.rs Outdated Show resolved Hide resolved
src/libstd/sys_common/parking_lot_core/util.rs Outdated Show resolved Hide resolved
src/libstd/sys_common/parking_lot_core/spinwait.rs Outdated Show resolved Hide resolved
src/libstd/sys_common/parking_lot_core/parking_lot.rs Outdated Show resolved Hide resolved
@rust-highfive

This comment has been minimized.

@rust-highfive

This comment has been minimized.

@rust-highfive

This comment has been minimized.

@bors

This comment has been minimized.

@RalfJung
Copy link
Member

RalfJung commented Dec 4, 2018

r? @RalfJung

FYI, I will not have time to look at this "+4168 −2426" PR this week. I should be able to get to it next week though.

I also feel slightly overwhelmed by the importance of this and would appreciate a co-reviewer -- maybe someone who actually has reviewed libstd code before :D

@faern
Copy link
Contributor Author

faern commented Dec 4, 2018

I should add that I'm currently working on improving this code. Will likely push changes in a day or two. I have already backported some of the feedback here directly to parking_lot and have managed to, at least slightly, reduce the amount of unsafe. As soon as I have reached some good state and my tests pass I will push things here.

@bors

This comment has been minimized.

@faern faern force-pushed the add-parking-lot branch 3 times, most recently from abc062b to 9718fba Compare December 9, 2018 02:01
@faern
Copy link
Contributor Author

faern commented Dec 9, 2018

I could post some kind of benchmarks. The parking_lot repo has a benchmark sub-crate in it that can perform some micro benchmarking of the Mutex and RwLock types. Please keep in mind these are micro benchmarks, and also that the numbers varies quite a lot between runs as well.

Mutex

Built using latest nightly rustc/libstd:

$ cargo +nightly run --release --bin mutex -- 2 1 0 1 2
- Running with 2 threads
- 1 iterations inside lock, 0 iterations outside lock
- 1 seconds per test
        name         |    average     |     median     |    std.dev.   
parking_lot::Mutex   |  27880.651 kHz |  27643.931 kHz |    784.495 kHz
std::sync::Mutex     |   5760.698 kHz |   5983.312 kHz |    244.146 kHz
pthread_mutex_t      |   7557.519 kHz |   7640.839 kHz |    258.375 kHz

Built using the code currently in this PR (stage1 compiler):

$ cargo +stage1 run --release --bin mutex -- 2 1 0 1 2
- Running with 2 threads
- 1 iterations inside lock, 0 iterations outside lock
- 1 seconds per test
        name         |    average     |     median     |    std.dev.   
parking_lot::Mutex   |  26761.369 kHz |  28265.800 kHz |   3176.551 kHz
std::sync::Mutex     |  21122.531 kHz |  20840.200 kHz |   1490.975 kHz
pthread_mutex_t      |   7654.629 kHz |   7509.882 kHz |    648.945 kHz

RwLock

Built using latest nightly rustc/libstd:

$ cargo +nightly run --release --bin rwlock -- 1 1 1 0 1 2
- Running with 1 writer threads and 1 reader threads
- 1 iterations inside lock, 0 iterations outside lock
- 1 seconds per test
parking_lot::RwLock  - [write]  44619.796 kHz [read]  11551.274 kHz
seqlock::SeqLock     - [write]  27633.108 kHz [read]  31532.853 kHz
std::sync::RwLock    - [write]   6450.503 kHz [read]   4018.782 kHz
pthread_rwlock_t     - [write]  11007.401 kHz [read]   8722.818 kHz

Built using the code currently in this PR (stage1 compiler):

$ cargo +stage1 run --release --bin rwlock -- 1 1 1 0 1 2
- Running with 1 writer threads and 1 reader threads
- 1 iterations inside lock, 0 iterations outside lock
- 1 seconds per test
parking_lot::RwLock  - [write]  38818.641 kHz [read]  15724.790 kHz
seqlock::SeqLock     - [write]  27193.925 kHz [read]  38514.387 kHz
std::sync::RwLock    - [write]  34072.830 kHz [read]   2120.811 kHz
pthread_rwlock_t     - [write]   9255.783 kHz [read]   8181.922 kHz

All of the above was on Linux.

@rust-highfive

This comment has been minimized.

@faern
Copy link
Contributor Author

faern commented Dec 9, 2018

I was able to remove the boxing of the inner locking type in the std::sync locking types. Since it's no longer important to keep the locks fixed at one memory address we don't need the box. For std::sync::Mutex this reduced indirection resulted in approximately 5% speedup in micro benchmarks on Linux, when there is contention. Compared to the performance std::sync::Mutex had with the code in this PR just before removing the boxing (the benchmarks posted above).

EDIT: Worth noting that this also affects the size of the synchronization structs. Mutex<()> went from 16 to 2 bytes.

@cormacrelf
Copy link
Contributor

@KronicDeth I made a PR for some single-threaded RawMutex/RawRwLock implementations that hopefully avoid the entire parking & timers subsystems altogether. Needs heavy review. Amanieu/parking_lot#187

bors bot added a commit to Amanieu/parking_lot that referenced this pull request Nov 16, 2019
191: Add initial parking_lot_core tests r=Amanieu a=faern

This library could use more tests, to be more robust. This was one of the things pointed out in the review of the integration into std in rust-lang/rust#56410

`WTF::ParkingLot` has a number of tests we can take inspiration from. And this is somewhat of a port of some of those tests. However, when I ported it 1:1 I found a race condition, so I had to implement the semaphore a bit differently.

I also got away without the tests relying on a working mutex or condvar implementation. Because we can't make the `parking_lot_core` tests depend on the higher level `parking_lot`, nor do we want to depend on locking primitives in std if we aim to become the base for those implementations one day.

Co-authored-by: Linus Färnstrand <faern@faern.net>
@RalfJung RalfJung removed their assignment Nov 20, 2019
@RalfJung
Copy link
Member

I am totally out of the loop on this and anyway don't have the resources for reviews as big as this, I am afraid... so I removed myself from the list of reviewers here.

@Pzixel
Copy link

Pzixel commented Jan 9, 2020

Are there chances that this PR became too outdated and big so it won't be merged at all?

I just read @matklad 's article about spinloks and became really interested in getting these in std.

@faern
Copy link
Contributor Author

faern commented Jan 9, 2020

The problem with this PR is not how outdated it is towards master. What is holding it back is how parking_lot is currently not meeting the quality standards of the standard library and won't be accepted as a part of it right now. See the review further up in this thread (#56410 (comment)). Everything in that review has to be fixed first, then maybe this can proceed.

@Dylan-DPC-zz
Copy link

@faern how about closing this PR and reopening it once the parking lot issues are settled? Would probably be easier that way

@jethrogb
Copy link
Contributor

Easier for whom? The triage team or people trying to stay abreast of progress on this issue?

@Dylan-DPC-zz
Copy link

Everyone. The author, reviewers, triagists

@faern
Copy link
Contributor Author

faern commented Feb 18, 2020

@Dylan-DPC It's not like I have the time to contribute to this now nor likely soon. I feel like many of the outstanding parking_lot issues are partially out of my hands / not related to integrating parking_lot into libstd to begin with.

For me personally it won't really be "easier" if this was closed. But nor would it be harder. Whenever a new PR is opened again we have to navigate back and fourth between two PR threads, but that is going to be doable. Maybe better than having a PR open forever that no one contributes towards.

@jethrogb has a point about that people might want to stay up to date with this and not miss when/if it finally starts moving again. But they can still subscribe to this PR and if a new one is opened, someone can just post a comment in this PR linking to the new one.

@faern faern closed this Feb 18, 2020
@Dylan-DPC-zz
Copy link

Yes @faern understandable. But even if kept open and it is ready to be merged, it will increase the number of conflicts this has with other prs.

@shepmaster
Copy link
Member

a new PR is opened again

You can reopen this one at that time.

@comex
Copy link
Contributor

comex commented Feb 19, 2020

Incidentally, on Darwin, pthread mutexes use priority inheritance, while parking_lot does not intend to implement it. As long as that's true, switching the default mutex to parking_lot would be a regression in some ways.

@eddyb
Copy link
Member

eddyb commented Feb 19, 2020

You can reopen this one at that time.

Note of caution (we should have this somewhere linkable IMO, or GitHub could just make it simpler one their side): always reopen before pushing to the branch, otherwise GitHub will hide the option to reopen.

However, even if you pushed, you can still recover by finding the commit the branch was previously on, and force-pushing that, which will unlock reopening the PR.

@jyn514
Copy link
Member

jyn514 commented Jul 15, 2020

Is there any chance this PR will land into Rust 1.38?

Quite unlikely. It's currently blocked on a lot of work being done inside parking_lot. See the review feedback from Alex further up.

For future readers who don't want to read through 300 comments, this is faern/parking_lot#1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
relnotes Marks issues that should be documented in the release notes of the next release. S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unix: RwLock is incorrect RwLock and Mutex on Window theoretically allows undefined behavior in safe code