You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hello, I’ve been diving into the Tokio source code to explore potential performance improvements, specifically around the global task queue. I’m considering replacing the inject queue with a lock-free implementation to reduce contention. However, I noticed that inject and idle in the Synced struct are currently protected by a single Mutex:
This is defined in worker.rs. I initially assumed this was necessary to ensure state consistency—e.g., to prevent a thread from parking right after a task is added to inject, missing it due to a race. But having looked through the code I haven't found a critical section where something like this can happen.
This change was added in 2023. Before that, inject and idle had separate Mutexes, and the scheduler seemed to work fine. It seems that the “park/unpark” logic hasn't changed significantly since then.
I'd appreciate it if anyone could help me:
Does the unified Mutex for inject and idle provide specific advantages in the current design that I might be missing?
Would separating the global queue (inject) from Synced and making it lock-free be safe, or could it introduce subtle issues (e.g., races between parking and task injection)?
Since the code historically worked with separate Mutexes, is there a reason the single Mutex is preferred now beyond simplicity?
I’d appreciate any insights or pointers to parts of the code I should double-check. Thanks!
The text was updated successfully, but these errors were encountered:
foreverjun
changed the title
Understanding the rationale behind the unified Mutex for Inject and Idle in Tokio's Scheduler
Can the unified mutex for Inject and Idle in Tokio's Scheduler be safely split?
Apr 2, 2025
Hello, I’ve been diving into the Tokio source code to explore potential performance improvements, specifically around the global task queue. I’m considering replacing the inject queue with a lock-free implementation to reduce contention. However, I noticed that inject and idle in the Synced struct are currently protected by a single Mutex:
This is defined in worker.rs. I initially assumed this was necessary to ensure state consistency—e.g., to prevent a thread from parking right after a task is added to inject, missing it due to a race. But having looked through the code I haven't found a critical section where something like this can happen.
This change was added in 2023. Before that, inject and idle had separate Mutexes, and the scheduler seemed to work fine. It seems that the “park/unpark” logic hasn't changed significantly since then.
I'd appreciate it if anyone could help me:
I’d appreciate any insights or pointers to parts of the code I should double-check. Thanks!
The text was updated successfully, but these errors were encountered: