3 ms·
I haven’t used Go, but I am fairly certain it’s not really trying to do the same things as Rust. IIRC, calling C from Go isn’t zero cost. It also includes a muc
by skavi 2y ago
I haven’t used Go, but I am fairly certain it’s not really trying to do the same things as Rust. IIRC, calling C from Go isn’t zero cost. It also includes a much larger runtime than Rust.
- adastra22 2y agoYes, calling C from Go has significant overhead for exactly this reason. It basically requires creating a stack and copying over all the current coroutine info into it. Depending on the application, this can be accelerated by maintaining a cache of stack objects to use, or by having a "noasync" mode of compilation with all the coroutine stuff turned off (making calling C zero cost again), or by having a producer-consumer channel to a noasync thread that gets stuff passed to it from coroutine land and calls out to C. Generally speaking, applications tend to either (1) exist as low-level shims or embedded code that doesn't use coroutines, (2) be large Rust projects that don't call out to non-Rust stuff often (e.g. a web server), or (3) large performance-sensitive applications that call low-level APIs frequently (e.g. games). The above solutions handle all three of these cases. What Rust chose instead was to optimize for a compilation mode which supports all three cases at once, with zero cost for FFI. This sounds nice, until you realize that what they traded off to get this was UX. Writing concurrency in Rust is lightyears better than C++, but it still sucks compared with Go or Erlang.
- skavi 2y agoThat sounds like a few different languages. And I think it’s fine to want a language like Rust that allows you to be less explicit about things. Based on what I’ve heard, you might just be looking for Gleam. But I don’t think it would be the right move to make Rust something that it’s not, just so people don’t have to think about what a Future is or isn’t.
- adastra22 2y agoYou never tried to await from within a synchronous function? There's stuff that you just can't do with Rust's approach to concurrency, that would be trivial if we allowed some limited cost abstractions (e.g. thunking the future in this case). Or just make all functions asynchronous but eliminate the state machine if it contains no yields. The whole point of higher level abstractions is making it so that developers don't have to think about stuff. It's what I love about Rust: with the borrow checker, I know that if it compiles then I am not going to be accessing mutable or already freed state. The language and the compiler get more complicated so that I don't have to think about stuff. Rust didn't go that way with concurrency. They instead opted to push that complexity (thinking about what a Future is or isn't) onto the developer. YOU have to think about "should this API call be async?" instead of letting the downstream user decide that.
- skavi 2y ago> You never tried to await from within a synchronous function? Whenever necessary I have been able to do this easily. Calling async code from a synchronous context is not an example of something which can’t be done in Rust today. > Or just make all functions asynchronous but eliminate the state machine if it contains no yields. The optimizer generally already cleans this up. > The whole point of higher level abstractions is making it so that developers don't have to think about stuff. It's what I love about Rust: with the borrow checker, I know that if it compiles then I am not going to be accessing mutable or already freed state. The language and the compiler get more complicated so that I don't have to think about stuff. The borrow checker is not “limited cost”. It is zero cost. > Rust didn't go that way with concurrency. They instead opted to push that complexity (thinking about what a Future is or isn't) onto the developer. YOU have to think about "should this API call be async?" instead of letting the downstream user decide that. There is no zero cost way of doing this.
- gmueckl 2y agoThe borrow checker is not "zero cost". That is a myth. It forces the use of non-zero overhead escape hatches (RefCell/Rc) almost every time when the code tries to do something nontrivial, that is, something actually worth doing.
- skavi 2y agoThe guarantees given to you by the borrow checker are zero cost. Once you’ve exceeded its capabilities, you have the choice to either pay a runtime cost (use RefCell and friends) or deal with maintaining and validating unsafe code.
- pjmlp 2y agoEven though I am not a big fan of its design, there are hardly any scenarios were Go doesn't fit other than cargo cult against automatic resource management languages. To the point that even disliking Go, I might favour it over Rust, unless using any kind of automatic resource management is forbidden, and I don't feel like reaching out to C++ for whatever reason.