feat: Avoid spawning async-io thread if possible#249
Conversation
583c2b2 to
65b0e9b
Compare
65b0e9b to
4be93d8
Compare
|
Not a blocker for this, but I guess there should similarly be a non-blocking way to drive the reactor without an
It would be nice to be able to use |
|
Unfortunately the only way to consistently poll I/O events across platforms is through a blocking strategy. You can nest |
1df67c8 to
23a2f30
Compare
This commit adds conditions that prevent the async-io thread from being spawned in certain cases. This is important because sometimes async-io is used in environments where spawning additional threads can interfere with other functionality in the program; for example, in DPDK poll loops. If there is only one async-io::block_on invocation, there is no need to spawn the "async-io" thread; we can just modify block_on to not give up the reactor if it can detect that it is the only block_on call running in the program. From there, we also need to avoid spawning the async-io thread if there are no resources left when block_on exits. This should allow async-io to not spawn additional threads in single-threaded programs where it is not needed. Signed-off-by: John Nunley <dev@notgull.net>
23a2f30 to
dd56200
Compare
| async-task = "4.7.1" | ||
| blocking = "1" | ||
| criterion = { version = "0.7", default-features = false, features = ["cargo_bench_support"] } | ||
| fastrand = "2.3.0" |
There was a problem hiding this comment.
| fastrand = "2.3.0" | |
| fastrand = "2.3" |
fogti
left a comment
There was a problem hiding this comment.
It looks quite good overall (I couldn't find any obvious mistakes), but I'm not familiar enough to vouch for its complete correctness.
Would it be possible to only support this for such platforms? 🤔 Even if we could only support Linux and one of the BSDs, that would be awesome. |
| } | ||
|
|
||
| #[cold] | ||
| fn init() { |
There was a problem hiding this comment.
defining this inside another function, unnecessarily forces indentation, which is always bad for readability IMO.
| BLOCK_ON_COUNT.fetch_sub(1, Ordering::SeqCst); | ||
| unparker().unpark(); | ||
|
|
||
| // Only wake the `async-io` thread iff there are live resources. |
There was a problem hiding this comment.
"iff" is also commonly used to mean "if and only if", but I think then the "only" should be right next to the "iff".
There was a problem hiding this comment.
I've never heard that before in my life so I'm not sure that it's common enough. 😂 Best to be clear IMHO.
There was a problem hiding this comment.
Okay, it might be more common among mathematicians.
| static ALIVE_RESOURCE_COUNT: AtomicUsize = AtomicUsize::new(0); | ||
|
|
||
| /// Raw unparker for the "async-io" thread. | ||
| static UNPARKER: OnceLock<parking::Unparker> = OnceLock::new(); |
There was a problem hiding this comment.
moving to 2 separate globals that are tightly-coupled and then to be handled in a thread-safe manner, and being accessed directly from multiple places, seems a bit dangerous to me. I am too tired right now to suggest something better though 😭 but I'll think about it..
This commit adds conditions that prevent the async-io thread from being
spawned in certain cases. This is important because sometimes async-io
is used in environments where spawning additional threads can interfere
with other functionality in the program; for example, in DPDK poll
loops.
If there is only one async-io::block_on invocation, there is no need to
spawn the "async-io" thread; we can just modify block_on to not give up
the reactor if it can detect that it is the only block_on call running
in the program. From there, we also need to avoid spawning the async-io
thread if there are no resources left when block_on exits. This should
allow async-io to not spawn additional threads in single-threaded
programs where it is not needed.
Currently draft while I work out the kinks.
Closes: #40