top | item 21465131

Rust async/await hits stable tomorrow

97 points| cdbattags | 6 years ago |github.com | reply

35 comments

order
[+] dang|6 years ago|reply
I appreciate the enthusiasm, but please wait until a thing actually happens before posting it here.

Otherwise we end up having to penalize the actual thing as a dupe, or have repetitive split discussion.

[+] cdbattags|6 years ago|reply
Sincerely sorry! Didn't know this was the policy.
[+] vbezhenar|6 years ago|reply
I don't understand the obsession with async code. I can understand it with JavaScript: browser environment was crippled and node copied that instead of making proper threading available. But for most environments it's not a problem. Just use thread pool and enjoy sane sequential programming model. Yes, it might not work for Google scale. But it should work for the vast majority of projects and if you really need to think about scaling, you should think about scalable architecture to be able to scale to multiple machines.

It's like every programming language and framework today suddenly decides to introduce those async primitives and I've yet to find a single use-case for it in my projects.

[+] jchw|6 years ago|reply
> It's like every programming language and framework today suddenly decides to introduce those async primitives and I've yet to find a single use-case for it in my projects.

Consider that maybe this is because your projects are not the intended targets of async programming.

Async is super not new. Fibers and CSP and etc. are not new. A lot of the benefit of better concurrency is exactly for stuff that scales horizontally, but just because you can scale to hundreds of boxes does not mean you want each box to be bottlenecked on how many connections it can handle. For servers you absolutely want to be able to use your nodes to their fullest. Demand for this is almost certainly driving programming languages.

10 boxes handling 10000 connections > 100 boxes handling 1000 connections (edit: each)

[+] swsieber|6 years ago|reply
> But it should work for the vast majority of projects and if you really need to think about scaling, you should think about scalable architecture to be able to scale to multiple machines.

Or not. To me, that's like saying "If you need to worry about how to fit your data in memory, you should just move to Hadoop, or something like that instead".

Async/Await is especially suited to Rust though because Rust is all about safety/performance/ergonmics. Async/Await in particular allows eliminating of unsafe blocks that one would have to use to achieve the same level of performance by manually implementing state machines for futures.

Also, generally speaking, I think futures are good, performant abstraction over asynchronous code. It's required a lot of work to get it to stable, and there's still a lot of work to be done to address the multitude of paper-cuts left, but the dividends are huge.

[+] Argorak|6 years ago|reply
Rust shines as a language that both allows threaded and async programming, especially by being able to model concurrency issues.

But async programming was always hampered by several issues, which made it's own code generation and syntax necessary. Mostly, that's borrowing over yield points.

This enables Rust to be a language about choice: you can easily mix async and threaded code, with both being supported by the language just as well. The magic is that the `async/.await` support doesn't come with a runtime, you can choose it yourself.

Want predominantly threaded stuff? Use a threadpool (and maybe `await` the result). Predominantly concurrency? Use a runtime like https://async.rs and let run your code on that.

[+] monocasa|6 years ago|reply
It's really nice on embedded systems for one. Share a single stack, but have blocking looking code. I really like the Rust model where astnc/await is mainly syntax sugar, and you can just code the state machine manually if you want.

Edit: It's also nice on servers, because even if you have memory for all of those stacks in a no astnc world, you def don't have cache for all of them. Splitting the data that needs to be saved between blocking points from the temporary data that gets you to the next block point (and reusing that memory on the next task) has benefits in a modern memory architecture.

[+] cletus|6 years ago|reply
So I work at Facebook and day in and day out use Hack (Facebook's split from PHP) and one thing that's ingrained in the programming model is the async-await model.

PHP/Hack have a model that I think is probably the best overall method for serving HTTP requests in that within the context of a single request, none of the code is multithreaded. I say this is superior because you don't have to worry about race conditions (largely), locking and all that. You might call services that do that but you're insulated from the multithreaded issues of that.

Anyway, knowing that Hack's async-await is strictly cooperative multitasking rather than being multithreaded so you get concurrency and non-blocking I/O without the mental and code cost of threads and locks.

That's why I think it's a big deal.

[+] bch|6 years ago|reply
> I've yet to find a single use-case for it in my projects.

This is the “concurrency vs parallelism” that (e.g.) Rob Pike goes on about[0], rightfully. I think to the uninitiated it can be tough to grasp (not commenting on whether YOU understand or not...). I use it daily, depending on circumstances, w a single-threaded network client that concurrently manages connections to perhaps hundreds of other machines. Most of the wall-time is spent waiting for something to occur on one of the remotes; “waiting in parallel” isn’t going to speed anything up, and nothing happens outside of the relatively infrequent events from the outside network to my client. I can’t forecast what is going to arrive on which socket, so I wait, and process asynchronously. GUIs will operate this way too. The pattern is suitable where you’re in a situation where: “something might happen sometime and I’ll need to do a (quick) bit of work in response”

[0] https://youtu.be/cN_DpYBzKso

[+] lacker|6 years ago|reply
If your code is simple with thread pools, it will be just as simple with async/await.

The biggest problem with thread pools is that you have a limited number of threads. Either because you set an explicit size limit, or you run out of memory. It's really annoying to debug deadlocks that happen because your thread pool is out of threads. So typically applications that use thread pools just don't use parallelism as much as they would if they could use async/await.

There isn't really any advantage of thread pools. Programming in Go, for example, it's very easy to write async calls and quite awkward to explicitly manage threads. But in practice, there are never really any reasons you miss having thread pools.

[+] topspin|6 years ago|reply
> Just use thread pool

Rust's Tokio runtime uses a thread pool. As does C#'s asynchronous runtime. Goroutines are also multiplexed among threads. Asynchronous primitives and multithread programming are not mutually exclusive, Javascript not withstanding.

Interestingly, one language is indeed bucking the trend. Java is introducing fibers (lightweight user-mode threads) that allow traditional (sane, as you call it) code to be efficiently scheduled so that it "performs as well as asynchronous code" without introducing new language primitives. So you'll have the opportunity to see which works best in important mainstream languages. One wonders if Java won't pull off a surprise win here.

> you should think about scalable architecture to be able to scale to multiple machines

No, sorry; that's not a viable approach. CPUs are highly concurrent beasts with dozens of cores. Using these inefficiently with traditional blocking threads is not feasible even if you can spread the inefficiency across "multiple machines." That would simply waste expensive hardware, power, space and cooling. Asynchronous techniques solve real efficiency problems in the real world; it isn't a fad. And you can't fall back to "most projects don't need it" in the context of advising others how to scale large systems; they do indeed "need it" and they will continue to gravitate to programming platforms that provide it while abandoning those that do not.

[+] Zekio|6 years ago|reply
The biggest benefit I see with Async code is that a thread can go back to the thread pool while you as an example wait for a response from a HTTP request to an external service
[+] adamnemecek|6 years ago|reply
Async is much easier to program than threads (even thread with Rust). You might be working very low-level where you don't have an OS and thus no threads. Rust's works on those devices too. Like you can use this to implement an OS.

I think that there's going to be a new os written in Rust. It will be much lower level than all the current OS. You don't need a lot of protection when the compiler protects you.

[+] brlewis|6 years ago|reply
> I can understand it with JavaScript: browser environment was crippled and node copied that instead of making proper threading available.

This is false.

Single-threaded async for the server side was popularized by nginx, which started in 2002. Somewhere in 2007-2009 the Tornado web server showed that even Python could be fast and scalable using this model. In 2009 when node was first released, single-threaded async was already a thing.

What made node interesting was that it came with a pre-existing language where nonblocking code was idiomatic. This removes a lot of the pain of single-threaded async that you see in something like Java where it's easy to accidentally use a blocking call. And speaking of Java, that's also where multithreaded is painful because generally you have mutability, so you really need to know what you're doing to avoid race conditions. At every line where you mutate anything, you have to ask yourself, "what if the thread gets preempted here?" In JavaScript you only have to ask the equivalent question on lines where you see `await`.

[+] timClicks|6 years ago|reply
Providing support at the language level gives application developers more tools. If they know their own application domain, perhaps they can make better scheduling decisions than a general purpose scheduler?
[+] leshow|6 years ago|reply
It's particularly a big deal in Rust where working with the base Future primitives was pretty hairy. With async/await I can write code that looks synchronous but has all the advantages of async.
[+] riquito|6 years ago|reply
Can we avoid posting "1 day earlier" news? We're just going to dilute the discussions
[+] wsgeek|6 years ago|reply
Async is great... all those times a thread is waiting for even fractions of a second can now be easily put to use... using the same thread if needed (a big win for single threaded Python for example).
[+] gdxhyrd|6 years ago|reply
That already happens with any competent scheduler, no?