Live data from Hacker News

Maybe Rust isn’t a good tool for massively concurrent, userspace software

bitbashing.io

241–250 of 624 posts

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#241

Earlier quoted context omitted.

> You are right that it is not strictly necessary, but in practice, it is so helpful as a guard against the yielding problem that it's ubiquitous. This is honestly shocking to hear. I would think that if people had bugs in their programs they would want them to fail loudly so they can be fixed.

As someone else said, it is not, strictly speaking, a bug. If your server receives a request that requires very computationally expensive work, is it okay to delay every other request on that core? That's probably not okay, and it'll show in your latency distribution. Folks would rather have every future time sliced so that other tasks get some CPU time in a ~fair way (after all, there is no concept of task priority…

Trying to solve the problem by frequently invoking signal handlers will also show in your latency distribution!

I guess if someone wants to use futures as if they were goroutines then it's not a bug, but this sort of presupposes that an opinionated runtime is already shooting signals at itself. Fundamentally the language gives you a primitive for switching execution between one context and another, and the premise of the program is probably that execution will switch back pretty quickly from work related to any single task.

I read the blog about this situation at https://tokio.rs/blog/2020-04-preemption which is equally baffling. The described problem cannot even happen in the "runtime" I'm currently using because io_uring won't just completely stop responding to other kinds of sqe's and only give you responses to a multishot accept when a lot of connections are coming in. I strongly suspect equivalent results are achievable with epoll.

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#242

Earlier quoted context omitted.

It would be swell if functions could be generic over this capability at compile time, so that you could get the same guarantees from the type system without implementing the same protocols more than one time.

Haskell supports this, but right from the start Rust was always wary of trying to add higher kinded types, which are necessary to support this.

As a Zig programmer I also get to enjoy this, but from the angle of language implementors not caring about type theory

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#243

Anyone know why there isn't a single type/interface that allows for consumers to supply any of Arc, Rc etc boxed values? I haven't investigated it deeply, but I was developing something in Rust, and whether something needs to be threadsafe or not is entirely on the consumer's use case... bad separation of concerns for the provider of a generic interface to have to specify the specific type of boxed value. 100% fine i…

You can use impl Borrow for that if the choice is static.

If it's dynamic, you can use Cow or the supercow/bos/... crates if you want Arc/Rc to be options as well.

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#244
post #213

Earlier quoted context omitted.

> async doesn’t imply multithreaded Async the keyword doesn’t, but Tokio forces all of your async functions to be multi thread safe. And at the moment, tokio is almost exclusively the only async runtime used today. 95% of async libraries only support tokio. So you’re basically forced to write multi thread safe code even if you’d benefit more from a single thread event loop. Rust async’s set up is horrid and I wish th…

No, tokio does not require your Futures to be thread-safe. Every executor (including tokio) provides a `spawn_local` function that spawns Futures on the current thread, so they don't need to be Send: https://docs.rs/tokio/1.32.0/tokio/task/fn.spawn_local.html I have used Rust async extensively, and it works great. I consider Rust's Future system to be superior to JS Promises.

Wow, I've been using tokio for years and never knew about this. Thanks!

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#245
post #22

Async Everything is a bad language. Async/await was a terrible idea for fixing JavaScript's lack of proper blocked threading that is currently being bolted onto every language. It splits every language and every library-ecosystem in half and will cause pains for many years to come. Everyone who worked with multi-threading outside of JavaScript knows that using actors/communicating sequential processes is the best way…

async/await actually originated in C#, not Javascript. C#'s author, Anders Hejlsberg also authored Typescript. Typescript's additional features like classes, arrow functions and async/await eventually crept into ES6+.

I actually think it was a great solution in JS/TS given it's a single threaded event loop. The lower level the language the worse of an abstraction it is though. So I think most of the complaints here about async Rust are valid.

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#246
post #28

Promise/Future style of async is just a bad idea regardless of language. It was used because of ineptitude of languages where it become popular, and its far easier to implement into GC-less languages than message-passing-based asynchronous, but it's just misery to write code in. I'd prefer to suffer Go ineptitudes just to use bastardised message passing called channels there rather than any of the Python/JS/Rust asyn…

Yes. That atomized model of concurrency where your state goes everywhere and you somehow collect it back at some point was always (literally) the textbook example of how not to do it. It was created to be an improvement over the Javascript situation, and somehow every language that had a sane structure adopted it as if it was not only good, but the way to do things. This is insane.

> It was created to be an improvement over the Javascript situation

I see this repeated everywhere in this thread. async/await originated in C# not JS.

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#247
post #210

Earlier quoted context omitted.

To me this kind of sounds like circular reasoning. Without function coloring there's no distinction that you need to know of. Can you elaborate?

It's nonsense. Async in rust is just syntactic sugar around a function signature. You can merrily call async functions from sync rust, you just have to know what to do with the future you get back.

"you just have to know what to do" is the problem. You can call any color from any color, but for some colors it's trivial, e.g. sync function from a sync or async one, or a non-failing function from a failing or non-failing one.

I don't want to be able to call fallible function from an infallible one trivially, I want the compiler to force me to specify what exactly I'm going to do with an error if it happens. Likewise for async-from-sync: there are many ways I could call these: I can either create a single threaded executor and use it to complete the future to completion, or maybe I want to create a multithreaded executor, or maybe I expect the future complete in a single poll and never suspend and I don't even need a scheduler.

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#248
Does anyone have links to resources that someone new to Rust should read on how to conceptualize async code in Rust? Based on reading the comments, it would seem there are ways to start with writing synchronous code, and if necessary make it async but do it in such a way that is runtime agnostic... don't just reach for Tokio.

If I'm implementing a library, how should I write it so that the consumer of the library doesn't have to pull in Tokio if they don't want to?

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#249

Earlier quoted context omitted.

> Also, non-async/await solutions for concurrency and asynchrony result in a more verbose, complex and bloated syntax I just write the same code that I would write if it were synchronous and it executes asynchronously.

How would your code look like if you wanted to fire off two concurrent requests and then consume their results later on? In C# it is just var user = service.GetUser(id); var promos = service.GetPromotions(category); var eligible = GetEligibility(await user, await promos);

I guess like this:

    var user = try alloc.create(@Frame(service.GetUser));
    user.* = async service.GetUser(id);
    defer alloc.destroy(user);

    var promos = try alloc.create(@Frame(service.GetPromotions));
    promos.* = async service.GetPromotions(category);
    defer alloc.destroy(promos);

    var eligible = GetEligibility(await user.*, await promos.*);
but the claimed difference is not present in this code. It is that GetUser and GetPromotions do not themselves know whether they are async. The author of service is able to just take some readers and writers or some types or objects implementing some protocols and use them, then service's methods inherit the async-ness of its dependencies.

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#250
post #3

I love Rust, but async is a hot mess and you cannot just write async code the same way that you write sync code. I'm getting more convinced that mixing the two is a bad idea, and that Go's approach of making everything sync with a single async channel primitive might be right. I'm currently plumbing through some logic to call a sync method on a struct that implements Future and it's... an interesting challenge. While…

Library developers can afford to deal with complexity much more than users of libraries. Offloading such work on highly skilled people developing the basic infrastructure is surely the right approach.

I totally agree that library developers are the ones who _can_ handle complexity, but I have found even some of the top Rust devs are making async mistakes -- either the APIs are not correct from an async perspective, or there are basic bugs like losing wakers. The latter is so common it's not funny.
Post reply on HN