The Downsides of C++ Coroutines
21–30 of 51 posts
Re: The Downsides of C++ Coroutines
#22Eh, I use them and am quite productive with them. Some of the downsides I don't really buy, for example, the argument regarding allocations. In a typical task engine, you're allocating state per task anyways. Sure you could have custom arenas and such, but you can do that with C++ coroutines also by overriding operator new/delete on the promise object. The lifetime concerns are par for the course when it comes to asy…
Re: The Downsides of C++ Coroutines
#23"C++" and "Coroutines". Who would have thought. But, considering the accelerated releases post C++ 11, I guess I'm not surprised.
Re: The Downsides of C++ Coroutines
#24I do not understand yet (open to explanations!) what is the difference between stackless and stackful coroutines in the fact that stackless should be cheap and even "collapsable" when nested in lifetimes but if it is not the case... stackful is cheaper . Are not stackless supposed to be more performant? In which cases? Yes I know their virality, potential heap allocations, etc.
First, stackful coroutines use the coroutine stack for everything they do. Stackless coroutines can use the normal thread stack for synchronous calls, and that stack can be shared across any number of coroutines. Per-coroutine allocation is only needed for asynchronous calls.
Second, for stackful coroutines you need to allocate the entire stack up front, and usually you have no way of knowing how much stack might be needed, so you need a conservative upper bound. Normal thread stacks have sizes in megabytes. (That doesn't necessarily correspond to actual memory consumption, since the OS will only reserve physical memory as needed, but the physical reservation for a given stack can only grow, not shrink. And even just allocating the virtual space has a cost.) Most of the time you can get away with stacks that are much smaller, only a few kilobytes, but at the cost of potentially crashing when you've consumed too much stack; it's hard to statically analyze maximum stack usage.
Stackless coroutines will, in general, only allocate memory as needed for each coroutine invocation, so not only are you wasting less memory, you don't have to worry about hitting an arbitrary limit. Allocation elision makes things more complicated since, as the blog post notes, you can end up wasting some memory, but compared to stackful coroutines it's peanuts. But they have the downside that heap allocations and deallocations are expensive; plus, splitting a "stack" of nested calls into separate heap allocations, usually far away from each other in memory, is worse for cache locality.
Re: The Downsides of C++ Coroutines
#25> Just like a normal function arguments are passed using registers and the stack, coroutines are using the same ABI as previously specified, however the code different is vastly different. > Finally at the end of the function the stack space initially reserved get’s reset to where it was initially when the function first call happens then returns to the caller. This post could use some editing. I'm having to reread e…
That being said, it is a great article. C++ and coroutines is a story that has been going on for a long time, and the result surprised me. In a bad way.
One bit me right from the start. I copied out an example and it crashed, and it turned out (after hours of searching, reading - the compiler and sanitisers sure weren’t any help) that the problem was that I’d inadvertently made a parameter const& (force of habit) and bound a temporary to it.
My answer to this is simply that I choose not to use coroutines. If I can’t force a compilation failure when I do something dumb, that spooks me.
For a feature released in 2020 it has far too many footguns. Ranges was similar when it came to lifetime footguns. It’s just something that makes it hard to take seriously the claims that it is legacy code that is the reason C++ has a bad rap for safety. Coroutines and ranges are modern features that can shoot your foot off if you don’t know the implementation, which is kind of contrary to the point of making a friendly wrapper over it all.
Re: The Downsides of C++ Coroutines
#26I do not understand yet (open to explanations!) what is the difference between stackless and stackful coroutines in the fact that stackless should be cheap and even "collapsable" when nested in lifetimes but if it is not the case... stackful is cheaper . Are not stackless supposed to be more performant? In which cases? Yes I know their virality, potential heap allocations, etc.
Two differences: First, stackful coroutines use the coroutine stack for everything they do. Stackless coroutines can use the normal thread stack for synchronous calls, and that stack can be shared across any number of coroutines. Per-coroutine allocation is only needed for asynchronous calls. Second, for stackful coroutines you need to allocate the entire stack up front, and usually you have no way of knowing how muc…
Re: The Downsides of C++ Coroutines
#27Earlier quoted context omitted.
I don't understand how it is any more verbose.
Because you have to keep explicitly passing state between each callback, rather than just using the same context (which still has the ability to delete things if needed).
Re: The Downsides of C++ Coroutines
#28Experience teaches me that the worst time to use a new design pattern or technique is _right after you learn about it_. The problem in your code base you thought about while learning the pattern was a useful proxy for where it could be applied, but that doesn't mean it's the right fit. Do it in a scratch refactoring, and wait a week or two before you consider merging it. And make sure you are emotionally as ready to…
I agree that you should always be ready and happy to discard or refactor code as needed. Requirements change, your assumptions may be wrong. But in practice I've more often seen the opposite problem, where organizations end up stuck on C++11 for a decade for no technical reason. It's good to explore the new stuff and eventually adopt what you can use.
Re: The Downsides of C++ Coroutines
#29> Just like a normal function arguments are passed using registers and the stack, coroutines are using the same ABI as previously specified, however the code different is vastly different. > Finally at the end of the function the stack space initially reserved get’s reset to where it was initially when the function first call happens then returns to the caller. This post could use some editing. I'm having to reread e…
It is due a bit of proof reading. There are some readability issues. That being said, it is a great article. C++ and coroutines is a story that has been going on for a long time, and the result surprised me. In a bad way. One bit me right from the start. I copied out an example and it crashed, and it turned out (after hours of searching, reading - the compiler and sanitisers sure weren’t any help) that the problem wa…
I agree with your conclusion of not using C++ coroutines, though. It seems like the design falls somewhere in the "worst of both worlds". I would rather either use a library that implements coroutines with the minimal amount of C and inline assembly if performance is critical, or some higher level abstraction that works well with all other language features.
Re: The Downsides of C++ Coroutines
#30> Just like a normal function arguments are passed using registers and the stack, coroutines are using the same ABI as previously specified, however the code different is vastly different. > Finally at the end of the function the stack space initially reserved get’s reset to where it was initially when the function first call happens then returns to the caller. This post could use some editing. I'm having to reread e…
I live eat and breathe a few deeply technical things (including c++) but am hampered by lack of proficiency at clear communication and expression. Becoming increasingly self-aware of this, seeing a fine article like this about a topic I understand, "in the wild" only underscores the importance. :)
I can feel myself automatically rewriting it, just like how typos jump out.
I wonder if that would be actually useful (a rewrite) to anyone.