Live data from Hacker News

Tokio 1.0 – async runtime for Rust

tokio.rs

151–160 of 422 posts

Re: Tokio 1.0 – async runtime for Rust

#151
post #77

I don't really get these modern async APIs. In languages like Javascript I thought they only made sense because JS interpreters are (historically) single-threaded, so you really have no choice but async to express some concepts. Fine. But in Rust you can just spawn threads, share data through channels or mutexes, use OS-provided async IO primitives to poll file descriptors and do event-driven programming etc... I tri…

> I guess I'm trying to understand if it's me who's missing something

No you’re not. There is a similar situation in Kotlin, which supports coroutines. Makes things more complicated and is often used for very questionable reasons.

This is why I’m excited about project Loom, which will use the same old thread abstraction but can be configured to use fibers under the hood instead. Java devs don’t even care that its not traditional threading, its the same API! This simultaneously solves the „coloredness“ problem of functions.

Re: Tokio 1.0 – async runtime for Rust

#152

Earlier quoted context omitted.

async does not make sense for a lot of people and I am deeply worried by hype-driven popularity of Tokio and async-std in Rust. Especially harmful is that common libraries like reqwest (for HTTP requests) pulls async.

If you think OS threads are "better" than async tasks, then use them. Other people want to use async, so they use it. Rust does not have a runtime and provides blocking APIs by default, but gives you the option to use async if you want to.

True, but everyday more and more libraries are getting tedious to use in blocking mode.

Re: Tokio 1.0 – async runtime for Rust

#153
post #126

Earlier quoted context omitted.

Based on this, the default value is 2MB: https://unix.stackexchange.com/questions/127602/default-stac... So that would mean a lot of memory for 1 million threads, 2TB of RAM. But you can change the default. With a 64k stack you'd use up ~68GB of RAM, which doesn't seem like a lot for 1 million threads and 1 million requests happening at the same time.

That is also the maximum stack size which shouldn't normally be reached. You'll have to be careful how you use memory when you're handling a million clients, either as async or threaded.

The point is that each stack need to be big enough for the worst case. That means it does not really scales to start many thousands of threads. While the futures themselves used in async code can be kept relatively small, as they only need to contain the state needed while awaiting.

Re: Tokio 1.0 – async runtime for Rust

#154
post #140
post #96

Earlier quoted context omitted.

Synchronous code is even easier to reason about than code using async syntax sugar.

No, multithreaded synchronous code is not easier to reason about than async. I think most would agree.

You probably think async code can't have deadlocks like threaded code can. Async is still multi-threaded it's just that the threads are done in user-space and contain an implicit global lock.

Re: Tokio 1.0 – async runtime for Rust

#155

Earlier quoted context omitted.

> async is mandatory for reqwest async is not mandatory for reqwest. It provides a blocking API as well. > reqwest is the default HTTP request library in Rust ecosystem There is no "default" libraries. There are popular HTTP clients other than reqwest that also provide blocking APIs such as isahc and ureq

reqwest provides a blocking API, but reqwest also always depends on Tokio. A blocking API doesn't help when I don't want Tokio in my dependency tree at all. I am using isahc, but that also doesn't help when (say) Rusoto AWS library pulls reqwest pulls Tokio pulls async.

Doesn't sound like a problem with async, just sounds like you disagreeing about what good deps for your deps are.

Re: Tokio 1.0 – async runtime for Rust

#156

Earlier quoted context omitted.

Most people are not writing the next nginx. They are writing web application servers behind nginx.

This, merely, means that the web application code will hold back what Nginx is capable of serving.

If you know that there will be 10k concurrent users in your application, go ahead and use async right from the start.

But for the rest of us, simple, blocking code will do just fine and save us a few headaches.

Re: Tokio 1.0 – async runtime for Rust

#157
post #144

Earlier quoted context omitted.

What "normal-sized Linux server" has 70GB of RAM?

One that wants to handle a million requests per second? Or would you want to do that with a Raspberry Pi? :-) > What "normal-sized Linux server" has 70GB of RAM? Also, why are you "quoting" what I did not say?

Air quotes.

Re: Tokio 1.0 – async runtime for Rust

#158

Earlier quoted context omitted.

There are some pretty bad usability problems with most async APIs too. One is they make your functions colored; async functions world best with other async functions while normal blocking functions work best with other blocking functions. They also introduce a lot of noise; putting async/await everywhere doesn't tell you anything interesting. Considering a normal-sized Linux server can handle a million threads withou…

> Considering a normal-sized Linux server can handle a million threads without much trouble, it really seems like misplaced effort Seems like that would use a lot of memory for all the stacks

Pending async waits have stacks to preserve too

Re: Tokio 1.0 – async runtime for Rust

#159
post #146
post #77

I don't really get these modern async APIs. In languages like Javascript I thought they only made sense because JS interpreters are (historically) single-threaded, so you really have no choice but async to express some concepts. Fine. But in Rust you can just spawn threads, share data through channels or mutexes, use OS-provided async IO primitives to poll file descriptors and do event-driven programming etc... I tri…

I had the same thing initially. The upside of async over a simple event loop is, in my experience, when things become less simple, and you end up with hard-to-read little state machines all over the place. With async, you can have your event loop, but the state machines are handled by the compiler. Code is like threaded code. That can be very convenient. Threads, obviously, accomplish the same thing, and arguably mor…

> A non-async function is "regular logic", it must complete without blocking.

Maybe one can enforce this convention in the particular project, but there's no ecosystem-wide consensus on this, and in fact I don't want this to be consensus. I write blocking non-async functions every day. Why am I wrong to do so?

Re: Tokio 1.0 – async runtime for Rust

#160
post #77

I don't really get these modern async APIs. In languages like Javascript I thought they only made sense because JS interpreters are (historically) single-threaded, so you really have no choice but async to express some concepts. Fine. But in Rust you can just spawn threads, share data through channels or mutexes, use OS-provided async IO primitives to poll file descriptors and do event-driven programming etc... I tri…

Async/await matters in Rust specifically because the borrow checker makes writing code without it difficult, inefficient, and unergonomic: http://aturon.github.io/tech/2018/04/24/async-borrowing/ (note that some of the details have changed here, but the thrust of it is very much the same.) That said, if you can get your job done without this stuff, that's fine too, but the reasons it was pursued specifically involve…

Ah that's a good point, it's true that the borrow checker can sometimes get in the way for event-driven architectures and async IO borrows.

That being said I can't shake the feeling that going for something like Tokio in such a case is a bit like healing a paper cut by amputating the arm. Sure, technically you don't have the original problem anymore...

Post reply on HN