4 ms·
I might need a lot of stuff in my software. Eventually. I might need distributed database, or to to scale it out to run on multiple machines, and then maybe Raf
by dpc_01234 3y ago
I might need a lot of stuff in my software. Eventually. I might need distributed database, or to to scale it out to run on multiple machines, and then maybe Raft, or reactive architecture, zero-copy IO, or incremental updates or ... or ... the list goes on and on.
Thinking too much and in particularly going with over complicated solutions from the very start because "might" is just bad engineering.
Also, even if I do need async in a certain place, doesn't mean I need to endure the limitations and complexity of async Rust everywhere in my codebase. I can just spawn a single executor and pass around messages over channels to do what requires async in async runtime, and what doesn't in normal and simpler (and better) blocking IO Rust.
You need async IO? Great. I also need it sometimes. But that doesn't explain the fact that every single thing in Rust ecosystem nowadays is async-only, or at best blocking wrapper over async-only. Because "async is web-scale, and blocking is not web-scale".
Edit: Also the "just use smol" comically misses the problem. Yeah, smol might be simpler to use than tokio (it is, I like it better personally), but most stuff is based on tokio. It's an uphill battle for the same reasons using blocking IO Rust is becoming an uphill battle. Only thing better than using async when you don't want to is having to use 3 flavors (executors) of async, when you didn't want to use any in the first place.
Everything would be perfect and no one would complain about async all the time if the community defaulted to blocking, interoperable Rust, and then projects would pull in async in that few places that do actually need async. But nobody wants to write a library that isn't "web-scale" anymore, so tough luck.
- the__alchemist 3y agoI also see the `Async` vs `blocking` false dichotomy in embedded rust discussions. `Async/Await` != asynchronous execution.
- vc8f6vVV 3y agoIn some sense it is. Async is a glorified future, and future is a glorified thread management, and threads are a way to facilitate asynchronous execution. You can also create a threadless runtime, but then you are relying on OS threads (e.g. I/O or XHR), otherwise you are simply combining function calls (for which we already have language syntax).
- Ar-Curunir 3y ago> I also need it sometimes. But that doesn't explain the fact that every single thing in Rust ecosystem nowadays is async-only, or at best blocking wrapper over async-only. Now that’s just plainly untrue.
- dpc_01234 3y agoYes, yes. You're right. Though it does sometimes feel like it.
- karmakaze 3y agoI guess one thing going for it is that then Rust is a lot more like Node, which could help increase its popularity. I wonder if Rust at some point in its history became self-serving (bigger == better).
- insanitybit 3y ago> But nobody wants to write a library that isn't "web-scale" anymore, so tough luck. It's more like "I want to be able to put timeouts in my code". 99% of why I want async is so that if something takes too long I can just stop that. That is incredibly hard to do without async.
- vc8f6vVV 3y agoNot sure about Rust, but in other languages that don't have async: create a queue, spawn a thread with your task, thread with sleep and wait for a message from any of those two. Kill the still running thread when you get the message. Can't say it's incredibly hard (unless it's Javascript or you work in a single-threaded model in general).
- insanitybit 3y ago> Kill the still running thread when you get the message This is extremely difficult. I mentioned elsewhere that the only way to kill a thread is through the pthread_cancel API, which is very dangerous. Languages with larger runtimes can get around this because they have all sorts of things like global locks or implicit cooperative yielding. So they don't ever have to "kill" a thread, they actually just join it when it yields.
- vc8f6vVV 3y agoAs I understand when you are blocked on I/O and sends a signal to the waiting thread, that system call will simply be released and return an error. Ruby (Java etc.) does make it simple because of GC, so I don't need to worry about file descriptor leaks etc. But talking about Rust, shouldn't it be a part of a thread management? Basically if an error happens during normal blocking system call, it goes through the same sequence, no? E.g. you have to release any thread-local allocations no matter by each way system call was terminated. Rust threads are supposed to be memory safe, not sure about file descriptors. I don't quite understand what you mean by "yielding" though.
- klabb3 3y ago
- Tigress8780 3y agoIO is not a part of the async runtime contract (I don't know if this is good or bad), and Tokio & futures famously have different `Async{Read,Write}` traits. I once had to do this [0] to adapt between them. This means that any crate that uses IO will be bound to a limited number of Runtimes. Everything being Tokio-only is pretty bad (though Tokio itself is great), but here we are... [0] https://github.com/bluejekyll/trust-dns/pull/1373#issuecomment-772495965 https://github.com/bluejekyll/trust-dns/pull/1373#issuecomme...