Live data from Hacker News

Looking at Unity made me understand the point of C++ coroutines

mropert.github.io

171–180 of 190 posts

Re: Looking at Unity made me understand the point of C++ coroutines

#171

Earlier quoted context omitted.

> It’s pretty clear you’ve never built a production-grade async state machine. Haha .. you have no idea. FWIW I've built frameworks exactly for that, and it's highly likely that you've unwittingly used one of them.

Uh huh. The person who gets confused by how co_wait() actually works and thinks that coroutines are "intimidating" wrote frameworks that I would have used to build our C++ compiler. Do you not understand that cl.exe doesn't use external frameworks? lmfao

I said used, as in used in your everyday life, by interacting with computer systems whose backend implementations you are blissfully ignorant of.

But yeah, if you want to win arguments then arguing against yourself and your own hallucinations, is in your case the best way to go.

Re: Looking at Unity made me understand the point of C++ coroutines

#172

Earlier quoted context omitted.

As an x-gamedev, suspect/resume/stackful coroutines made them too heavy to have several thousand of them running during a game loop for our game. At the time we used GameMonkey Script: https://github.com/publicrepo/gmscript That was over 20 years ago. No idea what the current hotness is.

Several thousand? What were you using them for? Coroutines' main utility is that they let you write complex code that pauses and still looks sensible, so for games, you'd typically put stuff like the behavior of an NPC in a coroutine. If you have thousands of things to put each in its own coroutine, they must have been really, really simple stuff. At that point, the cost of context switching can become significant.

> the cost of context switching can become significant.

Which is why a solution with no (or very tiny) context switching is preferred over one that's heavy to switch.

> they must have been really, really simple stuff

Yes, because they were low-overhead it was trivial to start them for all kinds of tiny things.

Re: Looking at Unity made me understand the point of C++ coroutines

#173

Earlier quoted context omitted.

Given a coroutine body ``` int f() { a; co_yield r; b; co_return r2; } ``` this transforms into ``` auto f(auto then) { a; return then(r, [&]() { b; return then(r2); }); }; ``` You can easily extend this to arbitrarily complex statements. The main thing is that obviously, you have to worry about the capture lifetime yourself (coroutines allocate a frame separate from the stack), and the syntax causes nesting for ever…

How is this better than the equivalent coroutine code? I don't see any upsides from a user's perspective. > The main thing is that obviously, you have to worry about the capture lifetime yourself This is a big deal! The fact that the coroutine frame is kept alive and your state can just stay in local variables is one of the main selling points. I experienced this first-hand when I rewrote callback-style C++ ASIO code…

Using shared_ptr everywhere is an antipattern.

The whole point of controlling the capture is controlling the memory layout, which is what C++ is all about.

Even with Asio, you don't really have to do this. It's just the style the examples follow, and Asio itself isn't necessarily the best design.

Re: Looking at Unity made me understand the point of C++ coroutines

#174

Earlier quoted context omitted.

Given a coroutine body ``` int f() { a; co_yield r; b; co_return r2; } ``` this transforms into ``` auto f(auto then) { a; return then(r, [&]() { b; return then(r2); }); }; ``` You can easily extend this to arbitrarily complex statements. The main thing is that obviously, you have to worry about the capture lifetime yourself (coroutines allocate a frame separate from the stack), and the syntax causes nesting for ever…

Isn't this basically what javascript went through with Promise chaining "callback hell" that was cleaned up with async/await (and esbuild can still desugar the latter down to the former)

This is literally what coroutines are, syntactic sugar to generate nested lambdas.

Except in C++ this removes a fair amount of control given how low-level it is.

Re: Looking at Unity made me understand the point of C++ coroutines

#175

Earlier quoted context omitted.

How is this better than the equivalent coroutine code? I don't see any upsides from a user's perspective. > The main thing is that obviously, you have to worry about the capture lifetime yourself This is a big deal! The fact that the coroutine frame is kept alive and your state can just stay in local variables is one of the main selling points. I experienced this first-hand when I rewrote callback-style C++ ASIO code…

Using shared_ptr everywhere is an antipattern. The whole point of controlling the capture is controlling the memory layout, which is what C++ is all about. Even with Asio, you don't really have to do this. It's just the style the examples follow, and Asio itself isn't necessarily the best design.

With callbacks you have to make sure that your data persists across the function calls. This necessarily requires more heap allocations (or copies) than in a coroutine where most data can just live on the stack.

Re: Looking at Unity made me understand the point of C++ coroutines

#176
post #142

Earlier quoted context omitted.

I'll continue to bite... What AAA 60+fps mobile game written Unity without coroutines are you referring to?

There's exactly 0 (zero) AAA games made with unity so it's going to be tough. They're all a terrible lag fest no matter how they're implemented

Genshin Impact makes billions and it's made in Unity. Seems to be good enough for them.

Re: Looking at Unity made me understand the point of C++ coroutines

#177

Earlier quoted context omitted.

Uh huh. The person who gets confused by how co_wait() actually works and thinks that coroutines are "intimidating" wrote frameworks that I would have used to build our C++ compiler. Do you not understand that cl.exe doesn't use external frameworks? lmfao

I said used, as in used in your everyday life, by interacting with computer systems whose backend implementations you are blissfully ignorant of. But yeah, if you want to win arguments then arguing against yourself and your own hallucinations, is in your case the best way to go.

Um... you might want to look at my profile. In addition to working at MS and Apple for two decades (where I touched everything from firmware, ring-0, and ring-3), I was on the team that created SoftICE [0]: the first commercial ring-0 debugger for Windows. I also created the automated deadlock detector for BoundsChecker [1], which requires an in-depth understanding of operating system internals.

> computer systems whose backend implementations you are blissfully ignorant of

I am extremely confident in my "backend" knowledge (of course, an actual systems engineer would never refer to their work as "backend").

You wrote a "C++ framework" that runs in the "backend" of a "computer system"? Do I have that right? Please let me know what it is so that I can decompile it and see how it was implemented!

[0]: https://en.wikipedia.org/wiki/SoftICE

[1]: https://en.wikipedia.org/wiki/BoundsChecker

Re: Looking at Unity made me understand the point of C++ coroutines

#178

Earlier quoted context omitted.

Yeah I agree that user threads are overused by programmers. For most situations, using an OS thread is going to be far easier to work with. People like to cite the drawback that context switching overhead becomes a problem when you have thousands of threads, but the reality is that most people are not writing software that needs to handle many thousands of users all at once. Using green threads to handle such large s…

Besides context switching, another issue with OS threads is that you need to carefully use synchronization primitives and watch for missing barriers. Green threads are a bit more forgiving.

Main point of real threads is that the are executed simultaneously on different cores (single core can of course still run few threads if needed), not by cooperative switching. Hence you need sync primitives so better get used to it. Having few threads on real cores can dramatically increase performance.

Green threads is just syntactic sugar around need to process multiple requests from a single real thread without blocking on io calls. It is somewhat helpful but it is a way around, not a generic recipe for performance increase and scalability

Re: Looking at Unity made me understand the point of C++ coroutines

#179
post #95

I do not find so called "green threads" useful at all. In my opinion except some very esoteric cases they serve no purpose in "native" languages that have full access to all OS threading and IO facilities. Useful only in "deficient" environments like inherently single threaded request handlers like NodeJS.

Yeah I agree that user threads are overused by programmers. For most situations, using an OS thread is going to be far easier to work with. People like to cite the drawback that context switching overhead becomes a problem when you have thousands of threads, but the reality is that most people are not writing software that needs to handle many thousands of users all at once. Using green threads to handle such large s…

Among the other things I write stateful multithreaded high performance backends for enterprise. Processing thousands of requests per second. Database is local to backend and only for persistence. All state resides in RAM. In this environment green threads provide zero benefit.

Even if I was talking to remote database with slow access ability of green threads to "handle" bazillion requests will just overload the database. There are no miracles around the laws of physics.

Re: Looking at Unity made me understand the point of C++ coroutines

#180
post #178

Earlier quoted context omitted.

Besides context switching, another issue with OS threads is that you need to carefully use synchronization primitives and watch for missing barriers. Green threads are a bit more forgiving.

Main point of real threads is that the are executed simultaneously on different cores (single core can of course still run few threads if needed), not by cooperative switching. Hence you need sync primitives so better get used to it. Having few threads on real cores can dramatically increase performance. Green threads is just syntactic sugar around need to process multiple requests from a single real thread without b…

> Main point of real threads is that the are executed simultaneously on different cores

Sorry, that's about as far from truth as you can get. Threads were a thing way before multicore was available. Windows got them since Win95/NT4.0, and these didn't support multicore, nor did most of OpenVMS machines where NT thread model originated run multicore (were there any multicore VAXen at all). The two main points for threads back then was to simplify concurrent IO and to be able to run a background computation without hanging the UI. Unix was different because it was initially oriented towards timesharing aka. running a single program for user, so threads were seen as redundant complexity (as were async IO - so even today "I want to run something yet be able get more user input at any time" can sometimes be a PITA).

And year, not everything needs scalability. Scalability is actually actively harmful for everything that's not a server. E. g. UI needs to be responsive - but that doesn't necessary mean "run on multiple cores", rather "being able to preempt low-priority stuff". And usually you don't want to deal with multicore synchronization.

MCUs rarely have multiple cores. Yet multi-threading is ubiquitous, and on most RTOSes threads are much closer to "green threads" than Windows ones. Through as I keep screaming in every coroutine thread, I really wish C stackless coroutines were a thing, you can't afford a stack for everything.

There are more to this world than the boring AWS crud.

Post reply on HN