-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Linux's io_uring IO interface (2x performance vs libevent) #10768
base: master
Are you sure you want to change the base?
Conversation
Wow, this looks great 👍 It's a lot of stuff 😄 We should try to extract some parts into preliminary PRs. The syscall feature should definitely be a separate item. |
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 will say this: I'm not convinced using raw syscalls instead of liburing is the right way to go. There is a lot of ways to get small details wrong, and liburing exposes a much friendlier interface than the raw calls.
…to keep the current event_loop interface working (upcomming commit)
As a reminder, there is no public API changes and everything is behind a "preview" compile flag, so there is very little risk of breaking something in production. Either way I believe the primary concern is about manutenability in the long run, as this is a fairly complex code to adopt. It is understandable for a change like this to be not so fast to accept. If there is anything I can do, I'm available. |
|
src/kernel.cr
Outdated
->Crystal::EventLoop.after_fork, | ||
->{ Crystal::Scheduler.event_loop.after_fork }, |
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.
Out of curiosity: why is that change needed?
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.
The event loop is now a class variable instead of a module. This is because the event loop implementation is detected at runtime, so it can't be a module anymore.
Co-authored-by: Sijawusz Pur Rahnama <[email protected]>
Co-authored-by: Sijawusz Pur Rahnama <[email protected]>
The latest merges from master I did introduced some bug or flaky behavior on the CI tests and I'll have to investigate what's going on to fix that. Before I put any more effort into this work I want to ask the core maintainer: Is this PR something that would eventually be accepted into Crystal or the added complexity will do more harm than good and this shouldn't be merged anytime soon? If it's the later, let's close this. |
I would very much like to merge this. More in #10740 (comment) Thanks for your great work pushing it forward! I think with the event loop for windows now in place we should be able to continue with the refactoring necessary for io_uring integration. |
in .writable_fd? | ||
@io_uring.wait_writable(@fd, @callback, timeout: timeout) | ||
@io_uring.submit_poll_add(@fd, Crystal::System::Syscall::POLLOUT, action_id: @action_id, timeout: timeout) |
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.
So hmm, if I understand this correctly, this make it so that instead of going through events and wait_read/writeable it just submits a poll instead? I see one issue with that and that is the case when several fibers wait on the same file descriptor - it will wake every fiber that has submitted a poll instead of just waking up the first fiber. This is a difference to how the non-uring fiber loop works and I'm not certain that behavior is something that is good enough as it may mean that when a fiber actually gets woken up the fd is no longer actionable as some other fiber may have acted on it.
Also known as "thundering herd problem"
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.
Right now the goal is to mimic the exact same behavior as libevent. This action_id
there points to a callback (see create_fd_write_event
). It will call io.resume_write
that will wake only one single fiber.
If the action_id
were a Fiber, then it would wake up that fiber upon completion. It is more suitable for other operations like read/write/connect/send/etc. Currently only we only do poll with a callback.
Hey there @lbguilherme @straight-shoota - highly looking forward to having this for Crystal! ❤️ What are the next steps here? Could we update the tracking issue #10740 with a roadmap, if necessary? |
Hi @z64! I'm having very little time to work on this lately, so things are going slowly. The current status is that the code done and has been refactored in-line with current master. It should be working, but there is a bug causing the CI to seg fault and couldn't find the cause yet. Help is always appreciated, ofc. |
Apparently there are also "I/O rings" on Windows since 21H2: https://learn.microsoft.com/en-us/windows/win32/api/ioringapi/ They are apparently very similar to |
There is, but they are different enough that it would still take a lot of work to support windows. And I don't know how much is supported, I only that original article about it and that was not really sufficient when it comes to what operations are there |
Could any Crystal maintainer take a look? This improvement is of great importance. |
This pull request has been mentioned on Crystal Forum. There might be relevant details there: https://forum.crystal-lang.org/t/curious-about-the-eventloop-updates/6825/1 |
This is a WIP implementation of the io_uring interface into Crystal's scheduler. I'm opening this PR for early review.
This was only tested with Linux 5.12 on an x86_64 machine but should work on Linux 5.4+.
Here is a benchmark to demonstrate the current performance gains:
Before:
After (with
-Dpreview_iouring
):(Linux 5.12, Intel Xeon E-2174G, inside a Docker container)
Hopefully, this can come in time for Crystal 1.1.0 :D
Fixes #10740. Informs #10766.