Live data from Hacker News

Why asynchronous Rust doesn't work

eta.st

191–200 of 305 posts

Re: Why asynchronous Rust doesn't work

#191

Earlier quoted context omitted.

While I understand that with Graal and .Net you can ostensibly make native, static binaries for Kotlin or C#, I'm very skeptical that it works well in practice. In particular, I'm guessing it will feel like swimming upstream, fighting an ecosystem and build tooling which mostly assume you're running on a VM. And then there's the question of performance... And of course, with Python your code will run 100x slower than…

With the modern JVM you actually have to work quite hard to write native code (Rust/C++/C) that outperforms an equivalent Java/Kotlin/Scala implementation. And it is quite easy to perform worse with a native implementation. Of course that is subject to various caveats: 1. Anything running on the JVM will need a 50-500ms of startup time. 2. The JVM implementation will not reach max performance until the runtime has op…

> With the modern JVM you actually have to work quite hard to write native code (Rust/C++/C) that outperforms an equivalent Java/Kotlin/Scala implementation.

For what kind of code? I've never experienced comparable performance between JVM and C++ implementations, and I've had the misfortune of writing a couple parallel implementations in recent years where it was literally an "apples to apples" comparison. C++ is faster by default and isn't particularly close, even if you ignore Java's startup and warmup time. I've never seen a native implementation run slower than a JVM one in my entire career, which has included a lot of Java.

This is the expected outcome and easily explainable in technical terms. Performance in modern systems is dominated by memory handling efficiency, where C++ is very strong and JVM is not.

Re: Why asynchronous Rust doesn't work

#192

Earlier quoted context omitted.

This may be a problem with async generally unless the language is designed specifically around async like Go is, which some profound tradeoffs to make it happen. (not criticizing that I think Go did a great job)

Zig managed to get async correct, if you ask me, but it's because I would call it "the lowest-level primitive to do what you need it to do" (shift the function frame over to a place that "might not be the stack"). If you think of it as a sugared "async" you will probably do it wrong. After a lot of wrassling with it, once I realized that it was a very shallow abstraction over what the hardware is actually doing, ever…

Zig's approach is really nice here, but it's also a notably easier problem to solve than rust has, since it's not trying to solve for parallel/concurrent safety.

Do you think Zig's approach would be feasible in Rust? I guess maybe you could do it, but the sync version would have to have the stricter constraints of the async version.

Re: Why asynchronous Rust doesn't work

#193

Earlier quoted context omitted.

> Of course, someone will ignore those criteria and come in suggesting OCaml/Reason... I hoped Go to be such a language, but it failed to fulfill my needs by throwing away all the PL knowledge that humanity has accumulated for decades. I still mourn for the missed opportunity by Google.

I considered mentioning "Go", and while it would be nice to have a Go with generics + sum types, it's also very nice having Go as it is today. In other words, it would be nice to have a "Go with those things" and a "Go without them" (predictable rebuttal: "But if Go supports those things, you would only have to use them when you wanted to!" Frankly though, the type system is absurdly overemphasized. Squabbling over t…

Java (and other JVM languages), as well as C# to a certain extent address the points you raise. Secondly, it's not true that golang has a minimal learning curve (I've seen senior engineers write bad golang code when they're onboarded - it takes time to learn the golang way of doing things and its quirks), and it's not even a fundamental goal to have.

Re: Why asynchronous Rust doesn't work

#194
post #159

Earlier quoted context omitted.

Rust had GC in earlier versions, see eg http://web.archive.org/web/20130607161259/http://pcwalton.gi...

Yes, and (to be clear to people who don't click your link) it was removed for exactly the reason that the parent commenter mentioned. Rust's lack of a pervasive GC is not intended to suggest that GC is not generally useful (even in a systems context), only that it's too difficult to satisfy the sort of extreme control that people demand of a low-level language if they are forced to find ways to work around the pervas…

Yeah I have done some work trying to optimize code written in GC'd runtimes, and eventually you will hit a wall.

GC is great for a lot of use-cases: for instance if I am writing a server-less application with mostly lambdas/cloud functions which pull data from a database and serve it to an HTTP response, the productivity gains you get with a nice high-level language will more than make up for a few pennies you might pay for a tracing garbage collector to run, and it's going to be plenty fast enough.

But when you have a case where every cycle/byte of memory counts, the GC is going to get in the way. Of course stop-the-world collectors are a catastrophe for performance, but even with modern generational GC it's essentially a part of your program's execution you didn't write and you have at best arms-reach control over which dictates hugely performance-impacting aspects of execution like memory layout.

Some GC'd languages have escape hatches to manipulate the GC process directly, but even those feel a bit like trying to drive a nail by hammering it with the butt of a screwdriver.

Re: Why asynchronous Rust doesn't work

#195

Maybe I'm stupid. But why is Rust so much harder than any other newish programs language. Dart is like all of my dreams come true at once, Rust still gives me nightmares. I seriously tried to learn it multiple times and failed repeatedly. I've created several Dart/ Flutter projects for myself and friends. Multiple C#/Unity projects. Python and JavaScript have paid my rent for the better part of a decade. But Rust, I…

> Dart is like all of my dreams come true at once, Rust still gives me nightmares. Dart is the worst new language I've tried and it should have died back when they (in retrospective rightfully) abandoned DartVM in Chrome plans. (FWIW I used Dart back in the AngularDart betas, before Angular 2.0 was released, when TypeScript didn't even have support for async/await. Back then Dart had some good ideas, the tooling was…

I'm going to have to disagree, straight up flutter fixes everything wrong with react native. I've wasted countless hours I'll never get back trying to get various Babel configurations to work. I guess typescript tries to fix issues with JavaScript not having real types, but you still have to fight Babel.

Why do I still need a bunch of weird configuration files to just get import working ? JavaScript has treated me very well, it's what allows me to pay my bills. It still has so many fundamental issues that I avoid it when I can.

The vast majority of apps ultimately either CRUD or LOB( thanks for the term). When I or a friend needs something hacked together real quick, Flutter is the answer.

Add in what might be the greatest Firebase integration, and that you can create CRUD apps in hours. Implement login, and authentication flows within minutes.

I don't feel like playing the true Scotsman game when it comes to getting things done, if it works it works.

In fact when I build these tools for my friends, or for myself I don't even build an app. I deploy directly to a website with Firebase and Flutter web. Google makes us workflow insanely easy, I could probably deploy a new CRUD app with a login system in like an hour.

Ultimately all we need to do is render a list of items, create new items, update them and delete them. That's what the vast majority of apps do.

At least for my personal projects it's Unity for games, and Flutter for anything else.

Then again, I don't have a comp science background and I just love getting things done. I don't really care how Flutter accomplishes what it does. Your allowed to use both Dynamics and Types when defining methods. This really helps when trying to hack something together fast, but latter reffing it.

If a friend needs an app built to track grocery spending or what not, what stack would you pick.

Re: Why asynchronous Rust doesn't work

#196
post #79

Earlier quoted context omitted.

> When async is visible in the type system it means you need to write things like iterating containers twice It should be noted that this is only if the type-system in your language is unable to properly abstract over containers and their capabilities. If it is powerful enough however, then you can write the code once, under the (important!) assumption of short-circuiting in the case of errors.

Sure, it's possible to parametrize your algorithms. However, do you need to explicitly parametrize them or does the language do it for you? I'm not aware of any language that would remove the need to consider them and just automatically "work" with async types whereas "normal" threading—with errors handled via exceptions—more or less work out of the box the way you expect.

> However, do you need to explicitly parametrize them or does the language do it for you? I'm not aware of any language that would remove the need to consider them and just automatically "work" with async types whereas "normal" threading

That's correct. What I said is: you can write your algorithm once and apply it to both sync and async datastructures (given certain constraints).

But that doesn't mean that async and sync feels exactly the same. It's simply impossible for this to be true in any meaningful way and has been tried over and over.

Re: Why asynchronous Rust doesn't work

#197
post #183

Earlier quoted context omitted.

its really strange that there are two languages running around together. one which is very opinionated in how to manage memory in a stack discipline and another which just uses reference counts. they don't quite mix. so you need to be aware of which one you're (implicitly using), and you may need library functions for both colors. you have to admit this adds some additional mental overhead. but what got me when tryin…

> its really strange that there are two languages running around together. Mmh, I'm not sure I would agree with that. I've been using Arc & Rc for both async and non-async code, and even in single-threaded code. It's less about what flavor of concurrency you're using, than what program you're writing. Arcs and references can coexist and are useful for different reasons. It would be a tragic loss for me if the languag…

my perspective is that everything I do is asynch and multithreaded. so the whole hierarchical allocation part of the language is largely useless to me.

once i figured that out, its really not so bad. but anytime a collaborator or a library tells me to use lifetimes I just get all churlish.

Re: Why asynchronous Rust doesn't work

#198
post #174

Earlier quoted context omitted.

its really strange that there are two languages running around together. one which is very opinionated in how to manage memory in a stack discipline and another which just uses reference counts. they don't quite mix. so you need to be aware of which one you're (implicitly using), and you may need library functions for both colors. you have to admit this adds some additional mental overhead. but what got me when tryin…

IME, using reference counts there is also not a good idea. In practice I think it's better to treat async tasks just like goroutines and then use channels to communicate.

I've found that when I've structured things that way in the past I do have some performance issues if the grain is very small.

more importantly to me is that those machines dont really compose that well over larger scales - that is to add a new component I need to look at the overall scheduling and connectedness of the existing components and need to rework them to order to handle a new control flow.

it is a nice model. i think it isn't appropriate for some things, so I tend not to reach for it by default.

Re: Why asynchronous Rust doesn't work

#199
"Maybe we could just have kept Rust as it was circa 2016, and let the crazy non-blocking folks write hand-crafted epoll() loops like they do in C++. I honestly don’t know, and think it’s a difficult problem to solve."

I think this is the most underappreciated part of this article. Since when did everything have to be async? There are other ways to represent concurrency that more accurately reflect what the computer is actually doing.

For example, an alternative to async is to represent a workstream as a state machine, where state transitions happen between I/O. Then, your state machine can be a struct, and each state transition can be an impl function on that struct that takes one or more completed I/O requests as input and emits one or more I/O requests as output. This saves you from having to implement everything as a closure, which this article rants about. Your top-level epoll loop merely services I/O requests from state machine instances, and invokes your global application logic to start and stop state machines to carry out business logic tasks.

I realize that many complicated workstreams could have many states due to all the I/O they might do, but the task of converting a high-level workstream into a state machine could be automated by the tooling.

Re: Why asynchronous Rust doesn't work

#200

Earlier quoted context omitted.

Well, 90% of what I am doing is writing libraries. I know how to get things right. Does Rust?

Honestly, as a consumer of libraries, I much prefer when they're written in Rust (without gratuitous use of `unsafe`) compared to a language which doesn't make you think about these sorts of things as hard.

For me, writing a program is mostly writing a bunch of libraries that I then put together. So I am consuming my libraries mostly myself. Therefore, for me it is important that both the library writing and the library using can be done efficiently.

I assume that having a Rust library of something is a good thing. The question for me is: How easy and natural and quick is it to express a concept as a library in Rust?

Post reply on HN