55 ms·
The viral aspect is the thing which really annoys me as well about it: I have some apps that make one or two single requests to DBs in certain configurations, a
by berkut 4y ago
The viral aspect is the thing which really annoys me as well about it: I have some apps that make one or two single requests to DBs in certain configurations, and I've had to end up using async for those parts (up to main() obviously, although not all code in the apps needs to be aware of async thankfully) due to many crates needing/using async now for this (which may well be good/fine for other peoples' heavy usage, but not really for my usage).
However, it means that even when these requests are not being done (and might never be for the running of the apps, as it's user-configured what the apps do and whether they make DB requests occasionally), these apps end up having some (it may not be much, but it's somewhat noticeable) overheads, i.e. coreCount threads are always created by the async infrastructure (despite being a single-threaded app in one of the apps cases), call stacks are deeper even though async is not really being used (although due to main() being async effectively that changes everything), meaning more memory usage for those threads's stacks (which is somewhat ironic, as that's one of the points of utilising async for heavy IO requests - reducing memory usage! - but in reverse it hurts my use cases a tiny bit).
Edit: I tried to use things like pollster (in an attempt to significantly isolate and limit the async usage to just where it was needed), and it wouldn't work for my use cases.
I'm on the verge of splitting the apps into two parts due to this, but due to the shared state, that would involve additional complexity (RPC or something), which I don't really want to stomach.
- SuperFluffy 4y agoYou can spin up a single threaded runtime to perform these async calls without the need to "infect" the rest of the program. The strategy is to spin up a single threaded async runtime and to just perform that call and block on the runtime itself. The easiest way to do that is probably https://github.com/zesterer/pollster https://github.com/zesterer/pollster And there really isn't much in there so you didn't need to worry about performance or anything like that. I recently refactored a colleague's program from async to sync because it's essentially and entirely sequential. The reason it started its life as async was the reqwest library, which first and foremost provides async methods to perform http requests. However, tucked away behind a feature flag aptly named `blocking` there is a small API that wraps the async api and allows making sync/blocking calls in a non-async main. And there they employ the same strategy of having a thin async runtime that blocks on completion of the async call.
- ibraheemdev 4y agoThis works with runtime agnostic futures, but you can't do any I/O without requiring a specific runtime. reqwest for example doesn't use a generic block_on, it runs tokio behind the scenes.
- armchairhacker 4y agoYou can spawn a simple Tokio I/O runtime with Builder::new_current_thread().with_io().build(). The catch is that it’s not really “simple”, and idk the performance penalty.
- berkut 4y agoI tried things like pollster, and they wouldn't work in my case for reasons I can't remember (but I asked for assistance on the Rust Discord and there didn't seem to be ways around it).
- Matthias247 4y agoA multithreaded runtime that is shared for all functions in the app - that other synchronous code then "blocks_on" - will also work. Or e.g. having a cached thread_local tokio runtime. Btw: > And there really isn't much in there so you didn't need to worry about performance or anything like that. Actually you have to! In case you write a program that spawns background threads (with whatever async runtime), and then let your foreground thread interact with that - it will have performance implications since your program now does additional context switches. It might or might not matter for your application, but in general it's rather easy to lose all perf benefits that async code actually might provide by still requiring switches between full threads.
- the_gipsy 4y agoI worked on a rust project that had one thread with a httpserver all async, and another thread with some mqtt client all sync. Communicate over channel. No big deal.