Live data from Hacker News

Async-std: an async port of the Rust standard library

async.rs

101–110 of 238 posts

Re: Async-std: an async port of the Rust standard library

#101
post #82
post #52

Earlier quoted context omitted.

In small examples like this, you don't gain anything. For the sake of the example, we just run one task. But you _could_ run 100 with them. And at each of those `awaits`, they could schedule differently. For a more complex networked application, we have the tutorial here: https://github.com/async-rs/a-chat

Wouldn't it make more sense to show an example that actually takes advantage of async/await? I don't get why they are using examples that need a disclaimer like you can run 100 jobs for this to make sense. So it should include that in the example (and it should probably do something that makes sense if it's run a hundred times).

The example is intended for you to be able to implement it, not as a showcase.

I think the expectation with Rust async-await at the moment is likely that people are familiar with async syntax from other languages e.g. Python - it's not even in beta yet, you need to be running nightly to get the syntax.

Re: Async-std: an async port of the Rust standard library

#102
post #5

This remind me of the blog post "What Color is Your Function?"[0], they had to create a different library that is the same as the standard library but with async functions. I thought Rust had other, better ways to create non-blocking code so I don't understand why to use async instead. [0] https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...

> I thought Rust had other, better ways to create non-blocking code so I don't understand why to use async instead. In fact, Rust does have a great solution for nonblocking code: just use threads! Threads work great, they are very fast on Linux, and solutions such as goroutines are just implementations of threads in userland anyway. (The "what color is your function?" post fails to acknowledge that goroutines are jus…

Threads are bad for high concurrency. Specifically when you need to call out to another service that has some latency.

Say you have 1000 threads. To handle a request each one needs to make 50ms of external or DB calls. In one second, each thread can handle 20 calls. So you can handle 20k requests/second with 1000 threads. But Rust is so fast it can serve 500k requests a second. So with regular threads, you need ~25,000 threads. The OS isn't going to like that.

With async you can run a single thread per core, with no concurrency limits. So you get your 500k requests without overhead. With fibers you just run 20k fibers which is a little bit of overhead but easy to do.

This is the core reason everyone is pushing async and fibers in fast languages. When you can push a ton of requests/second but each one has latency you can't control, regular threads will kneecap performance.

In "slow" languages like Python, Ruby, etc, async/fibers don't really matter because you can't handle enough requests to saturate a huge thread pool anyways.

Re: Async-std: an async port of the Rust standard library

#103
post #92

Earlier quoted context omitted.

This is missing a crutial explanation that the underlying OS API are asynchronous.

Yeah for sure. In Java/C# I see people do this all the damn time. Use async method for REST endpoints then make a blocking DB call. Or even worse, make a non-async REST call to another service from inside an async handler. As soon as you do that, your code isn't async anymore. And if you're using a framework like Vert.X or node that only runs one thread per core you're in big trouble. The most reasonable answer I've…

A message broker works here when you want async behaviour but you are integrating with sync code. To use your REST example, you receive the call, send a message to DoSomething and then immediately return http 202, perhaps with some id the ui can poll on (if required). Meanwhile, the DoSomething message queue is serviced by a few threads.

Re: Async-std: an async port of the Rust standard library

#104
post #18

Earlier quoted context omitted.

The point of asynchronous programming is to know exactly where concurrency happens in your code. This both eliminates concurrency bugs and gives you predictability for high performance.

Cooperative multitasking, like it's 1995 again? No thanks.

Why not?

Re: Async-std: an async port of the Rust standard library

#105

How does this relate to Tokio [0]? Why should I choose this new library instead? [0] https://github.com/tokio-rs/tokio

If all you needed from tokio was tokio::net, then async-std could work as a replacement for raw TCP stuff. If you needed the higher-level stuff from tokio like codecs then you'd not have those.

Also, anything from the tokio ecosystem like hyper would not work with async-std.

Edit: I originally had a first paragraph which was wrong. I mistakenly thought std::net::TcpListener is supposed to impl Read / Write.

Re: Async-std: an async port of the Rust standard library

#106

Earlier quoted context omitted.

Would you mind elaborating on your opinion here? As far as I understand, cooperative is far more efficient than preemptive, but unsuitable for poorly written or untrusted code. I wish to learn and would really appreciate your assistance if you are willing to help.

The key difference is cooperative multitasking lets the program yield the thread anywhere, not just to the event loop like async programming. Arbitrary yielding was a feature that programmers widely abused in the early Windows days. The user would start something in an app that takes some time to complete; the app would freeze for a while, but all other apps remained usable. It was obvious that the programmers, rathe…

>It's a good thing that async programming frameworks don't usually allow yielding from arbitrary places.

Well..

    await new Promise((res, rej) => { setImmediate(res); })
(In environments without `setImmediate` this is easily shimmed - https://github.com/YuzuJS/setImmediate)

Re: Async-std: an async port of the Rust standard library

#107

I must be dumb, because every time I dive into async/await, I feel like I reach an epiphany about how it works, and how to use it. Then a week later I read about it again and totally lost all understanding. What do I gain if I have code like this [0], which has a bunch of `.await?` in sequence? I know .await != join_thread(), but doesn't execution of the current scope of code halt while it waits for the future we are…

Right, that specific instance is essentially a single-threaded* application. Now imagine that you spawned a few hundred of them with JoinAll. Each would run, multiplexed within a single thread, with execution being passed at the await points. * anyone know the correct nomenclature for this? Single-coroutine?

Cooperative threads are still threads, they just aren't preemptive.

Re: Async-std: an async port of the Rust standard library

#108

I must be dumb, because every time I dive into async/await, I feel like I reach an epiphany about how it works, and how to use it. Then a week later I read about it again and totally lost all understanding. What do I gain if I have code like this [0], which has a bunch of `.await?` in sequence? I know .await != join_thread(), but doesn't execution of the current scope of code halt while it waits for the future we are…

> I must be dumb Nope, async really isn't trivial. > I know .await != join_thread(), but doesn't execution of the current scope of code halt while it waits for the future we are `.await`-ing to complete? It doesn't, that's the charm of it. It's best to treat 'await' as syntactic sugar, and to dig in to the underlying concepts. I realise we're not talking C#/.Net, but that's what I know: in .Net, your function might d…

> It's best to treat 'await' as syntactic sugar, and to dig in to the underlying concepts.

Slight word of warning: `async/await` is more than just sugar in Rust, it also enables borrowing over awaits, which was previously not possible.

Re: Async-std: an async port of the Rust standard library

#109

I must be dumb, because every time I dive into async/await, I feel like I reach an epiphany about how it works, and how to use it. Then a week later I read about it again and totally lost all understanding. What do I gain if I have code like this [0], which has a bunch of `.await?` in sequence? I know .await != join_thread(), but doesn't execution of the current scope of code halt while it waits for the future we are…

async/await are coroutines and continuations (bear with me).

Here is synchronous code:

    result = server.getStuff()
    print(result)
Here is synchronous code, that tries to be asynchronous:

    server.getStuff(lambda result: print(result))
Once server.getStuff returns, the callback passed to it is called with the result.

Here is the same code with async/await:

    result = await server.getStuff()
    print(result)
Internally, the compiler rewrites it to (roughly) the second form. That's called a continuation.

That's pretty much it.

A more involved example.

Synchronous code:

    result = server.getStuff()
    second = server.getMoreStuff(result+1)
    print(result)
Synchronous code that tries to be asynchronous:

    server.getStuff(
        lambda result: server.getMoreStuff(
          result+1, 
          lambda result2: print(result2)
    ))
A lot of JS code used to look like this hideous monstrosity.

Async/await version:

    result = await server.getStuff()
    second = await server.getMoreStuff(result+1)
    print(result)
Remember again, that it is basically transformed by the compiler into the second form.

Re: Async-std: an async port of the Rust standard library

#110
post #69
post #56

Earlier quoted context omitted.

The async-std is taking the “always red” approach that the article mentions and that wasn’t possible until now due to async being hot of the presses. The rest of the arguments in the article are based on the point that “red functions are more clumsy to call” which doesn’t hold for Rust, but holds for JavaScript.

The article explicitly admits that async/await is ergonomically much nicer than explicit futures/promises. But the color problem still remains, one consequence of which is duplication of code and interfaces. Arguing that the problem doesn't exist if you only stick to functions of a single color isn't a rebuttal, it's an admission! But the fact of the matter is async functions have real limitations and costs, which is…

I think the point is that "colored" functions only existed because Rust did not previously have async support. Now that it has async support, new code can be one color: async, while maintaining ergonomics.

Maybe new code will be exclusively async and existing code will switch over.

Post reply on HN