-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tokio: remove ref of scheduler in owned task #5992
Conversation
fac89f8
to
0126a7c
Compare
a274d68
to
4326c7a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please ask us before you spend a lot of time implementing something. I don't think this PR is correct, and I don't think it can be fixed. Unless there's something I'm missing, we will have to close this.
unsafe fn schedule<S: Schedule>(ptr: NonNull<Header>) { | ||
use crate::runtime::task::{Notified, Task}; | ||
|
||
let scheduler = Header::get_scheduler::<S>(ptr); | ||
scheduler | ||
.as_ref() | ||
.schedule(Notified(Task::from_raw(ptr.cast()))); | ||
let scheduler = Header::get_scheduler::<S>(ptr).as_ref(); | ||
let notify = Notified(Task::from_raw(ptr.cast())); | ||
match scheduler { | ||
Some(scheduler) => scheduler.schedule(notify), | ||
None => crate::task::schedule::schedule(notify), | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks incorrect. Consider this situation: An mpsc channel has the sender in runtime A, and the receiver in runtime B. Then, we send a message on the channel from runtime A. This causes the sender to call wake
on the waker stored by the receiver, which corresponds to a task from runtime B, but we are on the thread for runtime A. That call eventually hits this function, and then the None
branch of the match. This causes the task from runtime B to get scheduled on runtime A.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a test failure due to something similar:
thread 'runtime::tests::task_combinations::test_combinations' panicked at 'there is no reactor running, must be called from the context of a Tokio 1.x runtime', tokio/src/task/schedule.rs:19:19
stack backtrace:
0: rust_begin_unwind
at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/std/src/panicking.rs:593:5
1: core::panicking::panic_fmt
at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/panicking.rs:67:14
2: core::panicking::panic_display
at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/panicking.rs:150:5
3: tokio::task::schedule::schedule
at ./src/task/schedule.rs:19:19
4: tokio::runtime::task::raw::schedule
at ./src/runtime/task/raw.rs:286:17
5: tokio::runtime::task::raw::RawTask::schedule
at ./src/runtime/task/raw.rs:205:18
6: tokio::runtime::task::harness::<impl tokio::runtime::task::raw::RawTask>::wake_by_ref
at ./src/runtime/task/harness.rs:103:17
7: tokio::runtime::task::waker::wake_by_ref
at ./src/runtime/task/waker.rs:93:5
8: core::task::wake::Waker::wake_by_ref
at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/task/wake.rs:296:18
9: core::ops::function::FnOnce::call_once
at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/ops/function.rs:250:5
10: tokio::sync::oneshot::Task::with_task::{{closure}}
at ./src/sync/oneshot.rs:417:13
11: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with
at ./src/loom/std/unsafe_cell.rs:11:9
12: tokio::sync::oneshot::Task::with_task
at ./src/sync/oneshot.rs:415:9
13: tokio::sync::oneshot::Inner<T>::complete
at ./src/sync/oneshot.rs:1127:17
14: tokio::sync::oneshot::Sender<T>::send
at ./src/sync/oneshot.rs:608:13
15: tokio::runtime::tests::task_combinations::test_combination
at ./src/runtime/tests/task_combinations.rs:396:13
16: tokio::runtime::tests::task_combinations::test_combinations
at ./src/runtime/tests/task_combinations.rs:119:37
17: tokio::runtime::tests::task_combinations::test_combinations::{{closure}}
at ./src/runtime/tests/task_combinations.rs:68:24
18: core::ops::function::FnOnce::call_once
at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/ops/function.rs:250:5
19: core::ops::function::FnOnce::call_once
at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Here, the test calls oneshot::Sender::send
while it is not inside the runtime context. This panics because the thread-local is not available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got stuck on this this afternoon: The threads without context are hard to talk to the thread with context. This means the reference of scheduler have to put in something like channel, or in the tasks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I belive the message pass between sync threads and tokio runtime threads is a key capability, so the reference of scheduler in every task may have to be kept. To remove this reference, we may have to write a new tokio::spawn
method like tokio::spawn_without_....
, that is not a good way.
I believe this PR cannot resolve the above problem. |
Motivation
I belive we can remove the
Arc::clone()
call by removing the scheduler handle reference in all tasks.For those tasks are owned, we could always use the scheduler in thread local CONTEXT.
Solution
By removing ref(
Arc
) of scheduler in owned tasks, we could got a better performance, espically when we calltokio::spawn
very frequently in multiple threads.And we keep ref of scheduler in unowned tasks, which do not depend on the sheduler in thread local CONTEXT.
The cargo build can be more quickly by removing the generic parameter
S
.Here are the benchmark results of spawn2.
The current version:
This PR version: