Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> What we have now is a circus.

I couldn't agree more. And my conclusion is, as it has been, to stay away from async until we have a sane situation.



I'm new to Rust so please interpret this as curiosity and not criticism, but why not just use tokio? I understand that it's nice to build applications against a generic interface so that you can swap out libraries if one stops working well, but at this point tokio seems fairly well-vetted, and there are plenty of other parts of a typical stack that require some degree of lock-in: which database you choose, which web framework you build on, which cloud provider you interface with, etc., so I don't see choosing a specific async runtime as a deal-breaker. Could you elaborate on why you do?


Just a bystander with a curious question..

Is it possible to avoid async with Rust when you use most common 3rd party libraries? such as ones to make API requests, database connectors, date/time, logging, deal with special kind of files etc.? or are we talking "the burden is on the user to set feature flags and carefully choose which crates they import into their projects"?

Is it possible to set up the Rust toolchain to not allow async in a project at all?


> Is it possible to set up the Rust toolchain to not allow async in a project at all?

It's getting hard.

> Tokio's roots run deep within the ecosystem and it feels like for better or worse we're stuck with it.

Tokio has become a tentacle monster that is suffocating Rust.

Async is fine for webcrap, not good for embedded, and all wrong for multi-threaded game dev. The trouble is, the web back end industry is bigger than the other applications, and is driving Rust towards async. Partly because that's what the Javascript crowd knows.

Personally, I wish the web crowd would use Go. The libraries are better, the goroutine model, which is sort of like async but can block, is better for that, and garbage collection simplifies things. Rust is for hard problems that need to be engineered, where you need more safety than C++ but that level of control.


>Partly because that's what the Javascript crowd knows.

The "web crowd" leans towards async because most problems at scale where you would reach for Rust are almost always in a situation where they need to concurrently do a million tasks on 8 cpus. It's not because 'thats what the Javascript crowd knows', it's because, since the days of nginx (written in C), its been shown async i/o has better performance.

I don't see a lot of CRUD APIs in Rust - it's almost always database-like systems where the goroutine model and garbage collection cause a headache in terms of either memory usage or latency. I'm not sure if I agree that databases aren't "hard problems that need to be engineered".

That said, the reason Rust focuses so much on the web crowd, is because the majority of people paying the bills are the web companies. The Rust foundations biggest sponsors today are AWS, Google, Huawei, Meta and Microsoft (none of which I would describe as the "Javascript crowd"). AWS isn't hiring Rust engineers to work on game engines.

What I see more of is other industries just don't care about that much Rust.


> not good for embedded

embassy begs to differ

https://embassy.dev/

async/await is really just a syntax for building state machines in a way that resembles regular code. It's compiled down to the same code that you would write by hand anyway (early on it had some bloat in state size but I think it's all fixed now).

And embedded has a lot of state machines!


That was helpful to understand the problems with Tokio's dominance. As someone using Rust for web ... ehhhh ... stuff :-) I was always / still am happy with Tokio. But now I see the shadows Tokio casts.


The one web framework that took it slow on async adoption got absolutely pilloried for it.

There's very much a shiny new thing problem in the rust ecosystem.


You can use `block_on` from the futures-lite crate (or from other crates) to synchronously call async functions.

Not using async or async crates is not recommended since most new or updated high quality crates now use async.


And note that it's a good thing that crates are async, because async-in-sync using block_on has only some potential small CPU time overhead, while sync-in-async requires having a thread for each concurrent usage and has potentially catastrophic memory overhead since a user and kernel mode stacks and thread data structures could in some cases be 100-1000x bigger than the future; hence, an async-only create is much better than a sync-only crate (although of course a crate that supports both is ideal from the user's point of view).


That still requires pulling in the few hundred dependencies from tokio though?


That doesn't seem to be the case:

    ~> cd tmp\
    ~/tmp> cargo new futures-test
         Created binary (application) `futures-test` package
    ~/tmp> cd futures-test
    ~/tmp/futures-test> cargo add futures-lite
        Updating crates.io index
          Adding futures-lite v1.13.0 to dependencies.
                 Features:
                 + alloc
                 + fastrand
                 + futures-io
                 + memchr
                 + parking
                 + std
                 + waker-fn
    ~/tmp/futures-test> code .
    ~/tmp/futures-test> open src\main.rs
    use futures_lite::future;
    
    fn main() {
        future::block_on(async {
            println!("Hello world!");
        })
    }
    ~/tmp/futures-test> cargo run
       Compiling futures-io v0.3.28
       Compiling memchr v2.6.3
       Compiling pin-project-lite v0.2.13
       Compiling fastrand v1.9.0
       Compiling waker-fn v1.1.1
       Compiling parking v2.1.1
       Compiling futures-core v0.3.28
       Compiling futures-lite v1.13.0
       Compiling futures-test v0.1.0 (C:\Users\steve\tmp\futures-test)
        Finished dev [unoptimized + debuginfo] target(s) in 1.74s
         Running `target\debug\futures-test.exe`
    Hello world!
11 total dependencies.


Sure. But those async functions can't do any IO. If you need to use IO functions (e.g. from tokio), then you would still need to import that framework.


It is true that if you need to use Tokio, you'll end up using Tokio. That is not what was being suggested, though: it was just that tokio is not required for a simple block_on implementation. If you're already using tokio, using its block_on of course makes sense. But in that case, you're not adding "few hundred dependencies," you're using the ones that you're already using.

And like, to be clear, "the few hundred dependencies from tokio" is also misleading. A `cargo add tokio --features full` adds 43 dependencies to your Cargo.lock at the time of writing.


Thankyou for being correct and wonderful, as always. I was more aiming for the hyperbole crowd though man.


> such as ones to make API requests,

instead of reqwest you use ureq crate

> database connectors

can't answer at this time

> date/time

chrono crate has nothing to do with async

> logging

log crate with env_logger crate has nothing to do with async. pushing to something like elasticsearch instead of letting filebeat scrape your stdout is a different story

> deal with special kind of files etc.?

std::fs came first, the async stuff on top that recreate it in an async fashion came later. i'm pretty sure if you are dealing with a big file you can do std::fs with a "stream reader" basically


Hmm. As a developer, how would one learn if you want no async, "instead of reqwest you use ureq crate"? unless they happen to search on HN first? Is there a way to tell Rust tool chain that async stuff is to be disabled, and importantly, is there a way to search the crate library with a filter for no async?

Asking because I could only find a category for explicitly async crates, not the other way around.. https://crates.io/categories/asynchronous


> As a developer, how would one learn if you want no async, "instead of reqwest you use ureq crate"?

I just googled "synchronous rust http client" - the top result was a Stack Overflow question where the top (accepted) answer listed ureq as the first option.

(I'd still just use reqwest and Tokio though - practically speaking most of the concerns are non-issues in day-to-day work)


> (I'd still just use reqwest and Tokio though - practically speaking most of the concerns are non-issues in day-to-day work)

I actually did the opposite recently and replaced reqwest with ureq and managed to drop async and tokio altogether and greatly simplify my library. As a newcomer to Rust I kept getting pointed towards reqwest and tokio when ureq is far simpler.


Without knowing what your library does, it's hard to tell if the simplification benefit is worthwhile when traded off against the lack of usability from apps which should not be blocking worker threads. Could well be, but overall I'd just use Tokio and Reqwest (which has a module exposing a blocking API, even!)


I write a shitload of Rust and I think the situation is pretty sane. There are a few warts but the way people talk about it is insane - it's frankly not that bad at all and, mostly, quite good and easy to get started with.

I had already replied to this article over on lobste.rs

https://lobste.rs/s/iovz9o/state_async_rust

The tl;dr is that I think this entire async concern stuff is ridiculously overblown. I suspect the vast majority of Rust devs, like myself, not only accept the current state as "fine" (couple things to work on) but are very happy with the decisions tokio made.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: