[HN Gopher] C++20 coroutines and io_uring
___________________________________________________________________
C++20 coroutines and io_uring
Author : signa11
Score : 54 points
Date : 2022-11-13 15:17 UTC (1 days ago)
(HTM) web link (pabloariasal.github.io)
(TXT) w3m dump (pabloariasal.github.io)
| gavinray wrote:
| Hey just a heads up -- you're setting the queue depth of the ring
| to the number of files discovered, that's typically not the way
| you'd want to size the ring.
|
| When you start to get up into higher queue depths, like
| 512-1,024, you benefit a lot from using flags like
| IORING_SETUP_SQPOLL.
|
| If you're going to do a thread pool too, you may as well use
| IORING_WQ_ATTACH and put a ring on each thread that shares a
| single kernel poller, see the SO explanation I gave recently
| here:
|
| https://stackoverflow.com/questions/73798651/how-to-create-a...
| max_k wrote:
| I love C++ coroutines! (The spec has a few warts and gives me
| enough reasons to hate them, like not being able by definition to
| properly inline nested coroutine calls, but I love them anyway.)
|
| I've written several libraries for integrating C++ coroutines
| with stuff like io_uring, libcurl, c_ares, libpq and more. For
| example, this is how using my io_uring/coroutine library can be
| used:
| https://github.com/CM4all/libcommon/blob/master/test/co/RunC...
| auto result = co_await CoReadTextFile(queue, AT_FDCWD, path);
| co_await CoWrite(queue, STDOUT_FILENO, result.data(),
| result.size(), 0);
|
| This opens a file, stats it, reads its contents, and writes it to
| stdout - all 4 I/O operations are asynchronous with io_uring.
| Source code for CoReadTextFile() which is also a coroutine:
| https://github.com/CM4all/libcommon/blob/master/src/io/uring...
|
| Sample code for libpq:
| https://github.com/CM4all/libcommon/blob/master/test/co/RunC...
| and c_ares
| https://github.com/CM4all/libcommon/blob/master/test/co/RunC...
| and libcurl
| https://github.com/CM4all/libcommon/blob/master/test/curl/Ru...
|
| I wrote all of this for proprietary applications at dayjob, but
| the core library is open source, as is much of my dayjob code.
| The I/O event loop this integrates with is also used by several
| open source projects I maintain, e.g. the Music Player Daemon
| (https://github.com/MusicPlayerDaemon/MPD/tree/master/src/eve...)
| which can also take advantage of io_uring, though not (yet) with
| coroutines, only "classic" non-blocking I/O.
|
| My code is optimized for low-overhead; the very core doesn't even
| use std::function because I fear its implicit heap allocations.
| Long ago, I used boost::asio (which also integrates well with
| coroutines) but didn't like it because it was too bloated for me.
|
| I've rarely seen other nerds talk about C++ coroutines, and never
| about integrating them with io_uring, made me thinking I'm the
| only one. But maybe all the others just don't write/blog about it
| - I never did either... That's why this blog was a refreshing
| read for me, thanks.
| tlb wrote:
| I just converted something from libuv to asio and, while it has
| some advantages, it's definitely a huge dependency. And asio,
| perhaps in order to be standards-compliant, doesn't even do DNS
| asynchronously. I'd love a cleaner solution. My one painful
| requirement supporting both Linux and MacOS. Would you consider
| adding a kqueue implementation?
| max_k wrote:
| > Would you consider adding a kqueue implementation?
|
| Can't do, I don't have Apple or BSD anywhere. But if code for
| it were submitted to me, I would gladly merge it (and try to
| keep the CI happy).
|
| The MPD version of the event loop is portable and runs on
| macOS/BSD/Windows, but no kqueue, only poll() (and select()
| on Windows). This old-school API has its scalability
| problems, of course, but that matters not so much for MPD.
|
| The event loop can already do Coroutines on all supported
| targets; here's another open source project where I use this
| library:
| https://github.com/XCSoar/XCSoar/tree/master/src/event/ -
| it's a flight computer (yes, for real airplanes) which also
| runs on Windows and macOS and iOS, and runs libcurl (and
| other stuff) as coroutine.
|
| If you want to use my library and need help with integrating
| it or with adding kqueue support, get in touch with me.
| ptr wrote:
| How do you deal with errors? Do you check them at every
| callsite and manually "bubble up", or do you use exceptions?
| I'd love to use coroutines but we don't use exceptions and I'm
| not super excited about handling errors manually.
| max_k wrote:
| > do you use exceptions?
|
| Exceptions, sorry.
|
| I learned C++ in the early 90ies, but didn't like it much; I
| needed to do plain C for a few years at dayjob and several
| open source projects until I was fed up with manual error
| handling and go back to C++. At first with a "-fno-
| exceptions" policy (using something similar to GLib's
| GError), but gave up my resistance after a few more years,
| and now I enjoy exceptions very much. It's not perfect,
| nothing is, but everything else is uglier and so much more
| cumbersome.
|
| Exceptions seem inappropriate with writing non-
| blocking/asynchronous code, because where do you throw stuff
| when the caller is not on the call stack, but instead wants
| you to invoke a completion callback... but on the other hand,
| I don't want to implement two different kinds of error
| reporting - just look at the C++ standard library, which
| sometimes throws exceptions, sometimes uses std::errc - no, I
| wanted one single way to wrap error conditions, and I decided
| that std::exception_ptr is the way to go. All my error
| callbacks take an std::exception_ptr parameter, which they
| can then rethrow eventually, or pass on to the next error
| callback. Yes, I hate std::exception_ptr because it allocates
| memory on the heap, I despise implicit dynamic allocations,
| but everything else is uglier and so much more cumbersome. (I
| repeat myself.)
|
| Error handling is dirty, no matter how you solve it, but C++
| exceptions, with all their disadvantages, allow me to just
| consider the problem solved and go on with writing real code
| instead of keeping worrying everywhere. It just works.
|
| I know many projects and corporations have a strict "-fno-
| exceptions" policy and will not change their minds like I did
| - that's a matter of personal taste.
| pencilguin wrote:
| Others have integrated io_uring with asio, and asio with co-
| routines. The performance is about the same. The complexity is
| a matter of taste: asio offers lots built in that you would
| need to code yourself for the next project.
|
| I generally lean toward lower total complexity at cost if more
| custom coding, but it is a big tent.
| intelVISA wrote:
| We have an eerily similar coding style... I am now unnerved.
| max_k wrote:
| Whoa, that exists? How about having some nerd fun and we
| create a PR for each other's open source project?
| intelVISA wrote:
| Interesting... mail me? I will meditate on this.
| mrfox321 wrote:
| All new c++ code I work with at bigco are c++ coroutines.
|
| The underlying executors come from folly.
___________________________________________________________________
(page generated 2022-11-14 23:01 UTC)