Live data from Hacker News

Tokio 1.0 – async runtime for Rust

tokio.rs

281–290 of 422 posts

Re: Tokio 1.0 – async runtime for Rust

#281
post #272

It irks me that the "async runtime" isn't simply part of the rust runtime. Making it be a separate library simply increases the likelihood of having to deal with libraries expecting different version, or even different async runtimes entirely.

Rust doesn't have a runtime. That's part of its awesomeness. That's why it can target microcontrollers. You're probably used to languages with garbage collectors. Having garbage collection forces you to have a "runtime" since that's where the GC code goes. Then more and more stuff accretes onto this unavoidable runtime, and before you know it you're writing Java code...

Um, rust does have a runtime, that's why you don't need to include packages for strings, refcounting, allocation, etc.

Anything that has a language keyword should have a default implementation in that runtime, and much like box, ?, !, etc async and await are both language features that I shouldn't need to include from outside of the runtime.

Re: Tokio 1.0 – async runtime for Rust

#282
post #160

Earlier quoted context omitted.

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...

Can you elaborate a bit what it is that you find difficult or undesirable about Tokio? Or async/await + some runtime in general? So, I can relate to not wanting to pull in the dependency. But otherwise it seems pretty straightforward to me. You just macro-decorate the main function, sprinkle some async/await around, maybe add a join or a mutex somewhere, and then pretty much forget all about event loops, messaging, t…

I also don't get the async hype.

Maybe it is undesirable because that often times plain mono-thread synchronous is fast enough, easier to read, easier to debug and safe to handle to a junior ? Not everybody in a team has the same level of expertise.

And Rust is not an interpreted language. IMHO, interpreted languages should just drop to a compiled one to keep it KISS. Instead of going the async road, just to discover in production, it is unstable because back-pressure was not taken into account. And, in Rust, it is probably not worth the effort and ultimately bloat most of the time.

Re: Tokio 1.0 – async runtime for Rust

#283
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…

the "async/futures" way of writing code lets you write code that "looks like synchronous code" (write step 1, then step 2, then step 3, etc), while getting really good safety guarantees and not having to manage a state machine yourself.

The model doesn't work for all forms of concurrency, but I think it works for a lot of things that people at the "top of the stack" (application developers) do.

I don't know what kind of code you're looking at, in general, but you should be able to massage most async stuff into a list of things if you're not in callback soup. Granted, lots of people don't try to stay out of the callback soup, but.... I feel like even that is better than just like "try to validate concurrency invariants", which is a much harder problem for arbitrary code IMO?

Re: Tokio 1.0 – async runtime for Rust

#284
post #146

Earlier quoted context omitted.

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?

> I write blocking non-async functions every day. Why am I wrong to do so?

This (in my opinion) not "wrong". At least not in general. There are instances where it might be more or less probematic though.

It's probably problematic if you already have a bunch of async code in the codebase, because other readers of the code are likley to expect blocking functions to be async.

It's maybe problematic for high performance or high scale code. Synchronous blocking functions are more likely to hit OS limits (file handles, network sockets, etc) than async code. If the code is obviously written from the ground up for high scale/performance, this is less likely to be a problem, but if it's proof of concept code that's likely to get pushed into production by over eager PMs as soon as it passes tests, it'll be worse.

It's possibly problematic if done in a language/frameworks where async is idiomatic - it'd be wrong to write using blocking functions in a nodejs codebase, because you'd be breaking other people expectations when reading/understanding the code.

Maybe a useful rule of thumb might be "if more than some number (perhaps 30 or 50%) of other people working on the code might think 'hang on, I'm gonna refactor this to use async', then maybe using a non-asyn blocking function was the wrong choice. That means it's _never_ the wrong choice for one person codebases. It means it's probably almost always a wrong choice in a javascript codebase. For everything else? "It depends". I'd always choose to go with "the principle of least astonishment" - do whatever other people who might be affected would expect you to wherever possible.

Re: Tokio 1.0 – async runtime for Rust

#285
post #281

Earlier quoted context omitted.

Rust doesn't have a runtime. That's part of its awesomeness. That's why it can target microcontrollers. You're probably used to languages with garbage collectors. Having garbage collection forces you to have a "runtime" since that's where the GC code goes. Then more and more stuff accretes onto this unavoidable runtime, and before you know it you're writing Java code...

Um, rust does have a runtime, that's why you don't need to include packages for strings, refcounting, allocation, etc. Anything that has a language keyword should have a default implementation in that runtime, and much like box, ?, !, etc async and await are both language features that I shouldn't need to include from outside of the runtime.

What the OP is probably referring to is that Rust does not have a runtime in the typical sense used by languages such as Java. Rust does have a runtime, as all non-assembly languages do, but it is very very small. Languages with minimal runtimes like C or Rust are commonly referred to as having "no runtime".

Re: Tokio 1.0 – async runtime for Rust

#286
post #271
post #146

Earlier quoted context omitted.

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…

> Cross-thread communication is expensive. Single-threaded async task interaction is very cheap, comparatively This all depends on how threads are implemented. If they're scheduled preemptively then communication can be expensive, relatively speaking, because of the need for locking and atomic operations. But you can also schedule cooperatively in user space, just as Tokio does when serially resuming async tasks; or…

Bryan Cantrill's undergrad thesis would be cool to replicate today. 1:1 won because of performance pathologies in M:N.

Re: Tokio 1.0 – async runtime for Rust

#287

Earlier quoted context omitted.

Eh, so Rust is not for me? I seem to have heard Rust being inclusive and empowering everyone blah blah. I must have misheard.

It's clear this is one of your hobby horses. Every comment thread here is encumbered with you pointing out that you wouldn't like it if async were the default, fair enough. In fact, you don't seem to like the idea in general. ctrl-f "sanxiyn" yields 28 instances, most of them restating in every subtree the same point about how you think threads > async. Since I think most of us tend to read the comments section top t…

He's multi-threading ! (Sorry could not help myself :-D)

Re: Tokio 1.0 – async runtime for Rust

#290

Earlier quoted context omitted.

Here is an example: https://github.com/async-rs/async-std-hyper/blob/master/READ... You do have to write a ~50 loc compat layer. However, most of the compat layer is due to the fact that tokio's `AsyncRead` and `AsyncWrite` are different from the standard futures crate, which may change in the future [0]. After that, you just have to implement `hyper::Executor` for async-std's `spawn`, and `hyper::Accept` for async-s…

> tokio's `AsyncRead` and `AsyncWrite` are different from the standard futures The standard futures library does not have an AsyncRead or AsyncWrite: https://doc.rust-lang.org/std/future/index.html

Probably in reference to

https://docs.rs/futures/0.3.8/futures/io/trait.AsyncRead.htm...

vs

https://docs.rs/tokio/1.0.0/tokio/io/trait.AsyncRead.html

Post reply on HN