-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Added til::spsc, a lock-free, single-producer/-consumer FIFO queue #6751
Conversation
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 have some questions about some things that are probably not very important. Feel free to ignore.
BTW If you have a hard time understanding any part of the code, please let me know. I fully realize that the bit fiddling and atomics and stuff are kinda "meh" and this would allow me to improve the clarity of the code. |
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 incredibly clever, and I love it. I only understood roughly 80% of it, but it seems like it fits the brief and it comes with tests, and it's a great and concise and cross-platform piece of code. I'd be exceptionally proud to have this in our codebase. 😄
@msftbot make sure @miniksa signs off on this one |
Hello @zadjii-msft! Because you've given me some instructions on how to help merge this pull request, I'll be modifying my merge approach. Here's how I understand your requirements for merging this pull request:
If this doesn't seem right to you, you can tell me to cancel these instructions and use the auto-merge policy that has been configured for this repository. Try telling me "forget everything I just told 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.
I'm 99% sure we never covered this in my data structures or operating systems classes, so I think I'm not totally comprehending how this works. This seems sufficiently like magic to me.
That being said, reading through the arc
code wasn't as painful as it could have been, because there's more than enough comments. The only thing I want is more comments in the tests, and maybe more tests in general, as examples of how to use this.
This is great stuff, and I'm gonna sign off, but let's make sure @miniksa signs off too.
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'm generally good with this.
The only thing I'm left not understanding here is the memory orders. I read it here and I read it on the usual suspect website (cplusplus.com) and I still don't understand it. If you have a way of simplifying it for memory-ordering-idiots like me, please document it where each one is chosen why it works. Right now, I just trust that you (and @greg904) do understand it and you've worked out the optimal choices.
I'll hit approve after you clean up the final round of comments so as to not set off the AutoMerge bot.
Some notes from attempting to use this (that may turn into follow ons, not necessarily needed to merge this):
|
Maybe that's just a |
@miniksa Yeah you’re right about your second point. The first value of the pair is the resulting iterator and |
What if I just want as many as are ready even if the sender hasn't dropped yet (only waiting if there are none?) |
Okay, I tried using it here but with strings/wstrings instead of characters because I couldn't just "consume what was left". So I consumed one string at a time. https://github.com/microsoft/terminal/tree/dev/miniksa/gotta_go_fast_spsc It's doing pretty well. It's obvious that with a bounded queue, there's a backup that happens so it's not "as fast" as my completely unbounded one. But I didn't measure the memory usage on the unbounded one and it was assuredly bad. It is super simple to use, though. I used it very poorly in that branch and need to do better, but it proves the concept. If we can get a "consume whatever you've got even if the producer still exists" mode to pop, I think we'll be pretty good. And then my next phase will be identifying "simple text" on writing into the buffer and making that go faster as that's the new bottleneck... |
I thought about it in the car this morning, and I'm guessing this is just a symptom of a consumer that doesn't have enough to do. The producer spends a lot of time waking it back up again because it keeps consuming the whole queue and going to sleep. Probably not something that the spsc_queue needs to do anything about. |
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 documentation is excellent. Thank you so much
Audit mode, however, hates it. |
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.
Exactly what I was hoping for. Thank you.
Hello @miniksa! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
Summary of the Pull Request
This PR adds the
til::spsc
namespace, which implements a lock-free, single-producer, single-consumer FIFO queue ("channel"). The queue efficiently blocks the caller using Futexes if no data can be written to / read from the queue (e.g. usingWaitOnAddress
on Windows). Furthermore it allows batching of data and contains logic to signal the caller if the other side has been dropped/destructed.PR Checklist
Detailed Description of the Pull Request / Additional comments
til::spsc::details::arc<T>
contains most of the queue's logic and as such has the relevant documentation for its design.Validation Steps Performed
The queue was tested on Windows, Linux and macOS using MSVC, gcc and llvm and each of their available runtime introspection utilities in order to ensure no race conditions or memory leaks occur.