4 ms·
I've been on the fence for a while about coroutines, but I have to say that libraries like folly coro do a very good job at hiding all the complexity (the libra
by ot 5y ago
I've been on the fence for a while about coroutines, but I have to say that libraries like folly coro do a very good job at hiding all the complexity (the library itself though is somewhat impenetrable).
Facebook is very invested in coroutines, all major internal libraries at this point have a coroutine interface (in particular Thrift auto-generates coro client interfaces), and they have enjoyed wide adoption, way beyond the small cabal of C++ gurus.
Personally what sold me is cancellation handling. It really is magical.
Are your concerns about frame allocation? Is this something that the nanosecond-latency crowd particularly cares about? :)
- gpderetta 5y agoFor networking allocating the frame is perfectly reasonable because you need to allocate some sort of control structure anyway and you can do it off a custom allocator. In fact i think that stackful coroutines are probably a better fit. My issue is stackless coroutines would be perfect for generators but the required allocation kind of kills it :(.
- ot 5y ago> In fact i think that stackful coroutines are probably a better fit. My experience with fibers is that they're stack overflow generators. Presumably you want lots of them running concurrently, so you'll need a small stack size, and now you have to be extremely careful about what code you run in them as it's very easy to run out of stack. You can't rely on overcommit because if you actually end up touching the pages you're stuck with them. > My issue is stackless coroutines would be perfect for generators but the required allocation kind of kills it :(. That's true, though it depends on the granularity of the operations you want to run in your generators. Ranges+algorithms should cover most of the simple/small cases?
- new_realist 5y agoIn my experience, you overcommit virtual address space and have the compiler generate max stack size information. You then work to remove giant allocations. Not ideal, but the price for bespoke speed and debuggability.
- gpderetta 5y agoYou probably have more experience than me on this. I play with coroutines on my free time, but at $WORK is all state machines or explicit continuations (I want to avoid the hammer/nail problem). Having said that, I think that full coroutines can be no worse than stackless coroutines for stack usage. There are multiple options, including segmented stacks (which do have performance and ABI implications of course). My preferred solution would be to have first class continuations and have the compiler convert them to stackless coroutines if the calling continuation never escapes the top level frame. In fact even yielding from inlined, non recursive functions would still allow the conversion to be performed while giving better ergonomics than the current implementation. The trick here is how to extend the language in such a way that this can be a guaranteed optimization instead of QoI. If this can be made to work, I think the same exact optimization could remove the frame allocation for stackless coroutines. Unfortunately I suspect this might require adding the equivalent of rust lifetimes to C++. You can still avoid overflows even on a pure library implementation without compiler helps by switching to the main thread continuation (and its stack) for any stack consuming operation (or any operation that is known not to context switch). This can be extremely cheap, just an additional register swap over the normal function calling convention. YMMV.
- ot 5y agoWell, sure, you just need a sufficiently smart compiler :) > You can still avoid overflows even on a pure library implementation without compiler helps by switching to the main thread continuation Yes in fact that's what we had to do with fibers (see for example folly::runInMainContext()) but that means that all code that may be called from a fiber needs to be fiber-aware, which is not ideal.