Live data from Hacker News

Local async executors and why they should be the default

maciej.codes

51–60 of 327 posts

Re: Local async executors and why they should be the default

#52
post #38
post #35

I find all the async stuff in Rust incredibly ugly, cumbersome, and its one of the biggest reasons I prefer C++, still. C++ lets me just write single- or multithreaded code, because none of the dependencies force their `async` stuff on me. Yeah, its up to me to ensure things are synchronized, but I'd rather do that than try to figure out how to get some dependency that isnt meant to use async to work in some async mo…

Eh, in that case, you can also just write single or multithreaded Rust code, entirely ignoring async Rust. I do. And multithreaded Rust is much more pleasant experience than multithreaded C++. Which dependency is forcing async Rust on you? Alternatives are usually available.

Postgres (which is a wrapper around tokio-postgres, and as a result drags the whole tokio bloated dependency graph). I would love to have a purely sync alternative to that.

Re: Local async executors and why they should be the default

#53
post #32

In C# i always wondered why they couldn't hide the async/await logic for most cases. I never need to fire off two IO futures at the same time, so just make the thread do other stuff if i'm waiting for IO feedback, don't make me type out async/await in all impacted functions, let the compiler figure out when it can process other stuff

the use of async and await is a design decision that requires knowledge of the program's logic and desired behavior. It's not just a matter of compiler optimization, and that's why the compiler can't automatically figure out where to use these keywords. Suppose we have a service where users place orders, and we need to: 1. Save the order. 2. Deduct items from inventory. 3. Send a confirmation email. If we perform the…

I was thinking more in terms of making good old 'blocking' calls and that the compiler can 'taskify' those old blocking calls to let the thread do some other task instead of waiting on the 'blocking'

Re: Local async executors and why they should be the default

#54
post #25
post #15

While the article mostly focuses on the cognitive cost, which I deeply sympathize with, I do wonder about the runtime performance cost. Are there any good benchmarks actually quantifying the impact of all that extra thread-safety and the hoops that it adds? I'm not asking simply due personal interest in seeing the numbers, but also because if we want to steer the community towards this non-threadsafe direction it wou…

Anecdotal evidence, but many large rust async code bases perform significantly better if you are using a single threaded runtime vs. a multithreaded runtime. Here is an issue for the quinn crate that implements QUIC: https://github.com/quinn-rs/quinn/issues/1433 We have had very similar experiences when developing https://github.com/n0-computer/iroh And this is with quinn still carrying around the synchronization pri…

> Last but not least - often making futures Send requires you to box your futures. Send and lifetimes just does not play well together. Do something like this:

You should ~never need to box your futures to make them Send. You do sometimes need to box them to make them Unpin, but most of the time this is a tradeoff where it's possible to find a way to avoid moving them instead.

It seems like these screeds (both the OP and this reply) come from the misunderstanding that "X is hard, Y sometimes comes up in the errors when trying to do X, therefore X would be easy if we got rid of Y". In reality, Y often just demonstrates intricacies of X that you weren't thinking about.

Re: Local async executors and why they should be the default

#55
post #21

Earlier quoted context omitted.

Multi threading and concurrency are not the same. You can have a very high performance server that handles thousands of requests concurrently on a single thread. That's how node/deno do things. But the way to do things in async rust is that if you want concurrency you also have to use multithreading. At least that is what you see in all the examples and docs. As soon as you require your futures to be Send you have to…

> So e.g. you have to use Arc > In terms of C++ code that would equate to std::shared_ptr > which ... sounds quite wasteful in terms of scalability/performance. Why is it not possible to simply return a Rust promise? That's the way I do it in my C++ async (executor) library backed by work-stealing queues under the hood.

Not sure what you mean by "returning a rust promise". But yes, Arc> is a thread safe smart pointer containing a mutex, which has quite some overhead.

You will see this in many places in the internals of async code that has to be Send.

OK in many cases, but it can kill you if you have to go through this for many small operations.

Re: Local async executors and why they should be the default

#56
post #42

Async is and probably will always be less usable than blocking Rust. It is a very, very useful mode of operating when you really need two of its biggest benefits: lightweight cooperative concurrency and task cancellation, but it comes at a big usability cost. Rust software should use async tactically - in places where it is needed. Unfortunately handling http, which is a large part of many applications is actually a…

Your CRUD web application server almost certainly doesn't need async Rust. Using a blocking HTTP server is not "might be a good idea", it simply is a good idea. I recommend Rouille for this: https://github.com/tomaka/rouille . In case you are worried about performance, check the benchmark. Blocking Rouille is faster than builtin async server in Node.js.

>Your CRUD web application server almost certainly doesn't need async Rust. Using a blocking HTTP server is not "might be a good idea", it simply is a good idea.

How so? By what logic?

> Blocking Rouille is faster than builtin async server in Node.js

It isnt proof

Re: Local async executors and why they should be the default

#57

Earlier quoted context omitted.

I wonder if HN should have a rule that prohibits editorializing.

Maybe HN should auto-pull title from URL, and then add the posters title as a form of "subtitle/comment"

This assumes those titles are usable, which they often are not.

Re: Local async executors and why they should be the default

#58
post #18

This is bad editorializing. You're putting words in the author's mouth that cannot even be found on that page. Don't do that. Edit: Thanks to the mods or whoever fixed it.

I wonder if HN should have a rule that prohibits editorializing.

https://news.ycombinator.com/newsguidelines.html

Re: Local async executors and why they should be the default

#59
post #36
post #35

I find all the async stuff in Rust incredibly ugly, cumbersome, and its one of the biggest reasons I prefer C++, still. C++ lets me just write single- or multithreaded code, because none of the dependencies force their `async` stuff on me. Yeah, its up to me to ensure things are synchronized, but I'd rather do that than try to figure out how to get some dependency that isnt meant to use async to work in some async mo…

Your dependencies are what you choose them to be, you are not forced to use async libraries if you don't want to.

Technically true, but in practice you’re constrained by whatever is provided by the ecosystem. And the truth is that many Rust projects were forced to choose async or sync, so these are often disjoint and fragmented. Even within async, crate authors need to pick and choose which async ecosystem to support, due to lack of support in std for spawning tasks and running simple IO, which most projects need. This is slightly alleviated by the Tokio hegemony, but that itself is a deferred migration minefield for Rust to handle.

Re: Local async executors and why they should be the default

#60
post #39
post #35

I find all the async stuff in Rust incredibly ugly, cumbersome, and its one of the biggest reasons I prefer C++, still. C++ lets me just write single- or multithreaded code, because none of the dependencies force their `async` stuff on me. Yeah, its up to me to ensure things are synchronized, but I'd rather do that than try to figure out how to get some dependency that isnt meant to use async to work in some async mo…

I can see where you are coming from. But you can do most things purely in sync rust. There are sync rust multithreading libs like rayon that are a joy to use, and there are even blocking versions of popular http libraries like reqwest: https://docs.rs/reqwest/latest/reqwest/blocking/index.html They are usually doing some ugly stuff internally to make this work, but as a pure library user you don't have to care. If yo…

One thing I hate about "async" systems in general is the absurdity of suddenly having two types of functions behave differently with same syntax. And you have to add "await" keyword to async functions to make them synchoronous, i.e. behave normally.

I find the Go's approach of "everything is synchronous, except when made asynchronous with the 'go' keyword" much more pleasant and much less error prone. Is there a Rust library that does this - that provides coroutine-style asychronous behavior, but with synchronous Go-like syntax?

Post reply on HN