9 ms·
Have you ever heard of Esterel or Céu? They follow the synchronous concurrency paradigm, which apparently has specific trade-offs that give it great advantages
by vanderZwan 7y ago
Have you ever heard of Esterel or Céu? They follow the synchronous concurrency paradigm, which apparently has specific trade-offs that give it great advantages on embedded (IIRC the memory overhead per Céu "trail" is much lower than for async threads (in the order of bytes), fibers or whatnot, but computationally it scales worse with the nr of trails).
Céu is the more recent one of the two and is a research language that was designed with embedded systems in mind, with the PhD theses to show for it [2][3].
I wish other languages would adopt ideas from Céu. I have a feeling that if there was a language that supports both kinds of concurrency and allows for the GALS approach (globally asynchronous (meaning threads in this context), locally synchronous) you would have something really powerful on your hands.
EDIT: Er... sorry, this may have been a bit of an inappropriate comment, shifting the focus away from the Rust celebration. I'm really happy for Rust for finally landing this! (but could you pretty please start experimenting with synchronous concurrency too? ;) )
[0] http://ceu-lang.org/ http://ceu-lang.org/
[1] https://en.wikipedia.org/wiki/Esterel https://en.wikipedia.org/wiki/Esterel
[2] http://ceu-lang.org/chico/ceu_phd.pdf http://ceu-lang.org/chico/ceu_phd.pdf
[3] http://sunsite.informatik.rwth-aachen.de/Publications/AIB/2018/2018-05.pdf http://sunsite.informatik.rwth-aachen.de/Publications/AIB/20...
- mamcx 7y agoI also think async (the paradigm) is kind of weird in rust world. I agree with https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/ https://journal.stuffwithstuff.com/2015/02/01/what-color-is-....
- bryanlarsen 7y agoAll 5 of his points seem to be 2015 Javascript only. Some of them don't even apply to modern Javascript; I don't see any that apply to rust.
- vanderZwan 7y agoWhile I'm happy to believe you, with a short comment like that I just have to take your word for it. Could give a short explanation of how Rust already addresses each of these points for those of us who don't program in it?
- littlestymaar 7y agoThis article is 90% a rant against “callback hell” that js was facing before async/await was introduced. The remaining 10% stays valid even in the presence of async/await, but the trade-off (ignored by the article) of the alternative is having to manually deal with synchronization primitives (at least channels), which would make zero sense given that JavaScript is a single-threaded environment. Rust is a different beast, you can have whichever model you like best (OS threads, M:N threads (with third party libs), async/await) but async/await is by far the most powerful, that's why it's such a big deal that it lands on Rust stable.
- pcwalton 7y agoThe solution suggested by that article is to use M:N threading, which was tried in Rust and turned out to be slower than plain old 1:1 threading. If you don't want to deal with async functions, then you can use threads! That's what they're there for. On Linux they're quite fast. Async is for when you need more performance than what 1:1 or M:N threading can provide.
- mamcx 7y ago> If you don't want to deal with async functions, then you can use threads! Truly? If some very popular lib become async (like actix, request, that I use), I can TRULY ignore it and not split my world in async/sync?
- pcwalton 7y agoYou can easily convert async to sync by just blocking on the result. The other way (sync to async) is more difficult and requires proxying out to a thread pool, but it's also doable.
- BatmanAoD 7y agoAn `async` function _can_ call blocking functions, of course, it just blocks the entire thread of execution which could otherwise continue making progress by polling another future.
- nemothekid 7y agoBoth actix and reqwest are already async, the fact that you haven't noticed yet just shows that you are already ignoring it.
- mamcx 7y agoBut the signatures are not. If them mark the types/functions async, what happened? I must rewrite all the calls?
- danShumway 7y agoAuthor's solution is threads: > But if you have threads (green- or OS-level), you don’t need to do that. You can just suspend the entire thread and hop straight back to the OS or event loop without having to return from all of those functions. Correct me if I'm wrong, but wasn't the lack of threads one of the biggest reasons why NodeJS originally outperformed most of its competitors? Spinning up threads for each concurrent request was expensive, and (nonblocking) async code was by comparison ridiculously cheap, so the lack of overhead meant Node could just make everything async, instead of trying to decide up-front which tasks deserved which resources. Granted, it's been over a decade since Node came out. Maybe thread overhead has gotten a lot better? But barring faulty memory, I definitely remember a number of people explaining to me back then that being single-threaded was the point.
- IfOnlyYouKnew 7y agoI'm pretty sure that was the official talking point at the time, and some people may have even been motivated enough to actually belief it. Of course that all changed once Node got threads.
- BatmanAoD 7y agoDid it, though? AFAIK Node still doesn't have OS threads, which are the expensive version. The "About" page still says that Node is "designed without threads": https://nodejs.org/en/about/ https://nodejs.org/en/about/
- Rusky 7y agoIt's not the same, but Rust async/await tasks are also in the order of bytes, and you can get similar "structured concurrency"-like control flow with things like `futures::join!` or `futures::select!`. Ceu looks very neat, I suspect (having not read much about it yet) that async codebases could take a lot of inspiration from it already.
- vanderZwan 7y ago> you can get similar "structured concurrency"-like control flow with things like `futures::join!` or `futures::select!`. That sounds very promising, I should give it a closer look (I don't program in Rust myself so I only read blogs out of intellectual curiosity)
- naasking 7y agoOr you can use something like protothreads or async.h [1] if you're stuck with C/C++ and need something lightweight. [1] https://news.ycombinator.com/item?id=21033496 https://news.ycombinator.com/item?id=21033496
- vanderZwan 7y agoCéu compiles to C actually, and I believe Francisco Sant’Anna (the author of the language) makes a direct comparison to protothreads and nesC in one of his papers (probably the PhD thesis). I had not seen async.h before though, interesting! [1] http://ceu-lang.org/publications.html http://ceu-lang.org/publications.html
- kbenson 7y ago> Er... sorry, this may have been a bit of an inappropriate comment, shifting the focus away from the Rust celebration. I think if it's interesting and spurs useful conversation, it's appropriate, tangent or not. I for one an thankful for your suggested links, they look interesting.
- BatmanAoD 7y agoI hadn't heard of "synchronous concurrency", but looking at the Céu paper (only briefly so far), I think the model looks very close to how `async`/`await` works in Rust - possibly even isomorphic. This is really exciting, because Rust's model is unique among mainstream languages (it does not use green threads or fibers, and in fact does not require heap allocation), and I wasn't previously aware of any similar models even among experimental languages. I'll open a thread on users.rust-lang.com to discuss the similarities/differences with Céu, but for now, here's the main similarity I see: A Céu "trail" sounds a lot like an `async fn` in Rust. Within these functions, `.await` represents an explicit sync-point, i.e., the function cedes the runtime thread to the concurrency-runtime so that another `async fn` may be scheduled. (The concurrency-runtime is a combination of two objects, an `Executor` and a `Reactor`, that must meet certain requirements but are not provided by the language or standard library.)
- vanderZwan 7y agoThat is a correct understanding of how `await` works in Céu. What is important to note however is that all trails must have bounded execution, which means having an `await` statement. One abstraction that Céu uses is the idea that all reactions to external events are "infinitely" fast - that is, all trails have bounded execution, and computation is so much faster than incoming/outgoing events that it can be considered instantaneous. It's a bit like how one way of looking at garbage collected languages is that they model the computer as having infinite memory. Having said that, the combination of par/or and par/and constructs for parallel trails of execution, and code/await for reactive objects is like nothing I have ever seen in other languages (it's a little bit actor-modelish, but not quite). I haven't looked closely at Rust though. Céu also claims to have deterministic concurrency. What it means by that is that when multiple trails await the same external event, they are awakened in lexical order. So for a given sequence of external events in a given order, execution behavior should be deterministic. This kind of determinism seems to be true for all synchronous reactive languages[0]. Is the (single-threaded) concurrency model in Rust comparable here? The thesis is a bit out of date (only slightly though), the manual for v0.30 or the online playground might be a better start[1][2]. [0] which is like... three languages in total, hahaha. I don't even remember the third one beyond Esterel and Céu. The determinism is quite important though, because Esterel was designed with safety-critical systems in mind. [1] https://ceu-lang.github.io/ceu/out/manual/v0.30/ https://ceu-lang.github.io/ceu/out/manual/v0.30/ [2] http://ceu-lang.org/try.php http://ceu-lang.org/try.php