Live data from Hacker News

Why asynchronous Rust doesn't work

eta.st

181–190 of 305 posts

Re: Why asynchronous Rust doesn't work

#182

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…

For me, when learning a new language, there's a war in my brain between learning the thing and being productive. If I'm not productive long enough, I jet. It took me a couple of tries of bouncing off of Rust before it started clicking. I've written a few personal web projects in Rust and I'm still on the fence using it for those. My comparable Go web apps run just as fast with a little more memory usage, but are significantly faster to iterate on (compiler speed) and write, and also to read/understand later. The thing that has been tripping me up the most as an intermediate Rust programmer is that some library authors tend to get Architect Astronaut-y with the type system. It gives me the SimpleBeanFactoryAwareAspectInstanceFactory Java vibes.

Re: Why asynchronous Rust doesn't work

#183
post #73

Earlier quoted context omitted.

The article is also conflating synchronous single-threaded, synchronous multi-threaded and asynchronous programming. Each have their own usage, and no, a multi-threaded program is not the same as an asynchronous one. For example, using threads and channels instead of async/await is not a design flaw if your workload is mostly about large, blocking computations on a read-only shared state with no I/O. In that situatio…

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 language was (re-)adopting garbage collection or reference counting globally -even optionally. They are made to go along one another.

Edit: for example, tree-like or graph-like structures can use Arc and Weak [see arc documentation] in single-threaded code to enjoy reference-counted, cyclic, heap allocations in order to store a reference to a parent or sibling node.

You can do that with boxes, but Arcs have benefits if you want your code to work in a multithreaded environment.

Re: Why asynchronous Rust doesn't work

#184
post #124

Earlier quoted context omitted.

> I see this article as not understanding the goals and tradeoffs of Rust. The author would be happier writing in a higher-level language than Rust. That's a pointless conclusion. The author's criticisms of Rust's tradeoffs are invalid because those are the tradeoffs Rust made. A perfect circle!

That would be circular, but that's not what the parent is saying. Rather, eta's post has one central point - she even bolds it for us: > Rust is not a language where first-class functions are ergonomic. And this... I mean, I don't agree with her, but that might be because I've been immersed in Rust for half a decade. But Rust's tradeoffs are based around four things. It is a: - performant - reliable (incl. memory saf…

These things can be simultaneously true. The closure design is as good as it could be given the constraints, and it is not ergonomic.

Re: Why asynchronous Rust doesn't work

#185

Earlier quoted context omitted.

From my very limited expeirience with Rust I noticed that it becomes way more easy and laid back language when you just skip using references and lifetimes nearly completely and just wrap everything in Rc . Then you are getting expeirience of fairly high level language with a lot of very cool constructs and features like exhaustive pattern matching and value types with a lot of auto-derived functionality. Does Rc hel…

`Rc` freezes the value as long as it's shared unless you use interior mutability. It's fine when you want to share immutable data, but if you ever need to mutate its contents you will have to deal with awkward cases and situations, and at runtime! Wrapping everything in `Rc` is not a good default strategy. Instead figure out an architecture that works well with the borrow checker! This normally means thinking hard ab…

> If it's hard, then it's probably wrong!

Trees and graphs?

Re: Why asynchronous Rust doesn't work

#186
post #77

Earlier quoted context omitted.

I think it's not entirely fair to paint problems with rust's async features as an aversion to low-level-ness. If anything, I think the issue with Rust's async is that it tries to be too high level . In my experience with async rust, most of the difficulty comes from "spooky errors at a distance". I.e, you're writing some code which feels completely normal, and then suddenly you are hit with a large, obtuse error mess…

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, everything clicked.

Re: Why asynchronous Rust doesn't work

#187

There are constant efforts to make async easier in all languages. It'll never be as easy as writing synchronous code. I really don't like futures/promises, I don't know where this abstraction came from. Callbacks are where it's at. Someone, somewhere has to write callback code; they cannot be got rid of. What works for me is keeping the callback handler as short as possible, this usually means just pushing 'work' ont…

I've found async to be straight forward anytime I've used it. Promise#then is equivalent to callbacks

async/await often requires very little changes compared to synchronous code, whereas reworking a program into callbacks is much more impactful. & the async/await compilation process tends to produce better performance in addition to this. My first async/await work was a few years ago to increase a data importer's performance by an order of magnitude compared to the blocking code (I also used it a couple years earlier for a GUI (PointerWare) where code would await opening new windows, it wasn't really being used for concurrency there, just a nice interface of "show pop up, wait on that view to complete" which made Back buttons easy)

Here's an example where looping made for a callback that recursively called, using async/await I get to use a plain loop:

before: https://github.com/serprex/Befunge/blob/946ea0024c4d87a1b75d...

after: https://github.com/serprex/Befunge/blob/9677ddddb7a26b7a17dd...

Callbacks make it difficult to send information up the call chain, as the caller fires it off without a ticket to wait on the result. libxcb is an example of a library which optimized on libx11 by having functions which return cookies which func_reply wait on, these functions could similarly be implemented as an async/await interface

I don't see why people find it so complicated to separate begin-compute & wait-on-compute

I've rewritten a nodejs game server into rust, https://github.com/serprex/openEtG/tree/master/src/rs/server... handleget/handlews are quite straight forward. But apparently it doesn't work

Re: Why asynchronous Rust doesn't work

#188
post #102

Earlier quoted context omitted.

Nah, you're really not. Most of the time, particularly if you're not writing libraries, Rust feels like a dialect of Python that wants to help you get things right.

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.

Re: Why asynchronous Rust doesn't work

#189

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 good and it looked promising. In the meantime TypeScript did everything better while being backwards compatible and JavaScript improved a lot, along with the tooling. Now days Dart is strictly inferior in my view, the object model is closed/static, type system is nominal, so it has none of the scripting language qualities, and the runtime/metaprogramming is limited, with shitty library ecosystem - it's a shittier version of Java.

It's a language designed by VM developers and it shows in every way possible, so much emphasis placed on how the implementation works - for a high level language that isn't that performant in the end anyway and is hardly the bottleneck in it's usage scenarios.

Meta programming is done with compile time code generation and there is no runtime reflection, look at the libraries built for dealing with immutability for example - the ergonomics are Java level bad.

Flutter is a good idea if you need to write cross platform LOB apps (it becomes a bad idea if you need to use native components and render in coordination with them because the async channel native communication introduces visible render lag, eg. if you try to build custom rendering overlays over native maps it will lag frames behind because by the time you receive the map viewport updates and rerender the native map moved forward).

The fact that Flutter is built on top of Dart means I will not touch that framework any time soon, and would recommend anyone who doesn't like writing Java style boilerplate to avoid it as well.

They would need to include serious quality of life features to the language, and these features were requested years ago, but they move at a snails pace and prioritise other stuff.

Re: Why asynchronous Rust doesn't work

#190

Earlier quoted context omitted.

`Rc` freezes the value as long as it's shared unless you use interior mutability. It's fine when you want to share immutable data, but if you ever need to mutate its contents you will have to deal with awkward cases and situations, and at runtime! Wrapping everything in `Rc` is not a good default strategy. Instead figure out an architecture that works well with the borrow checker! This normally means thinking hard ab…

> If it's hard, then it's probably wrong! Trees and graphs?

The borrow checker gets to actively tell you that your family tree has some inbreeding!
Post reply on HN