-
-
Notifications
You must be signed in to change notification settings - Fork 147
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add scheduled time per task (#406)
Each task displays the sum of the time it has been idle and busy, as well as the total. The idle time includes the time between when a task is woken, and when the runtime actually polls that task. There are cases where a task may be scheduled for a long time after being woken, before it is polled. Especially if many tasks are woken at the same time and don't yield back to the runtime quickly. To add visibility to this, the total time that a task is scheduled before being polled has been added. Additionally, a new task state `Scheduled` has been added. This is displayed in both the tasks table and in the task detail view. In the `console-api`, the total `scheduled_time` for the task has been added to the `TaskStats` message in `tasks.proto`. This is the first of two parts. In the second part (#409), a histogram for scheduled time will be added, the equivalent of the poll time histogram which is already available on the task detail screen. To show a pathological case which may lead to needing to see the scheduled time, a new example has been added to the `console-subscriber` ## PR Notes This PR does something adjacent to what is described in #50, but not quite. The unicode character used for a `SCHED` task is ⏫. The second PR (#409) will record a scheduled time histogram the same as it recorded for poll times. These two changes should go in together (and certainly shouldn't be released separately). However, this PR is already quite big, so they'll be separated out. The idea is that this PR isn't merged until the next one has also been reviewed and approved. It would be good to get some feedback at this stage though. The task list view with the new column for `Sched` time: <img width="1032" alt="a tasks table view for the long-scheduled example" src="https://user-images.githubusercontent.com/89589/232456977-2921f884-4673-420f-ba4f-3646627d44db.png"> The `Task` block in the task detail view showing the new `Scheduled` time entry. <img width="510" alt="The task block on the task detail view for the rx task in the long-scheduled example" src="https://user-images.githubusercontent.com/89589/232457332-e455e086-9468-42c9-8fda-7965d8d1e6f8.png">
- Loading branch information
Showing
10 changed files
with
230 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
//! Long scheduled time | ||
//! | ||
//! This example shows an application with a task that has an excessive | ||
//! time between being woken and being polled. | ||
//! | ||
//! It consists of a channel where a sender task sends a message | ||
//! through the channel and then immediately does a lot of work | ||
//! (simulated in this case by a call to `std::thread::sleep`). | ||
//! | ||
//! As soon as the sender task calls `send()` the receiver task gets | ||
//! woken, but because there's only a single worker thread, it doesn't | ||
//! get polled until after the sender task has finished "working" and | ||
//! yields (via `tokio::time::sleep`). | ||
//! | ||
//! In the console, this is visible in the `rx` task, which has very | ||
//! high scheduled times - in the detail screen you will see that around | ||
//! it is scheduled around 98% of the time. The `tx` task, on the other | ||
//! hand, is busy most of the time. | ||
use std::time::Duration; | ||
|
||
use console_subscriber::ConsoleLayer; | ||
use tokio::{sync::mpsc, task}; | ||
use tracing::info; | ||
|
||
#[tokio::main(flavor = "multi_thread", worker_threads = 1)] | ||
async fn main() -> Result<(), Box<dyn std::error::Error>> { | ||
ConsoleLayer::builder() | ||
.with_default_env() | ||
.publish_interval(Duration::from_millis(100)) | ||
.init(); | ||
|
||
let (tx, rx) = mpsc::channel::<u32>(1); | ||
let count = 10000; | ||
|
||
let jh_rx = task::Builder::new() | ||
.name("rx") | ||
.spawn(receiver(rx, count)) | ||
.unwrap(); | ||
let jh_tx = task::Builder::new() | ||
.name("tx") | ||
.spawn(sender(tx, count)) | ||
.unwrap(); | ||
|
||
let res_tx = jh_tx.await; | ||
let res_rx = jh_rx.await; | ||
info!( | ||
"main: Joined sender: {:?} and receiver: {:?}", | ||
res_tx, res_rx, | ||
); | ||
|
||
tokio::time::sleep(Duration::from_millis(200)).await; | ||
|
||
Ok(()) | ||
} | ||
|
||
async fn sender(tx: mpsc::Sender<u32>, count: u32) { | ||
info!("tx: started"); | ||
|
||
for idx in 0..count { | ||
let msg: u32 = idx; | ||
let res = tx.send(msg).await; | ||
info!("tx: sent msg '{}' result: {:?}", msg, res); | ||
|
||
std::thread::sleep(Duration::from_millis(5000)); | ||
info!("tx: work done"); | ||
|
||
tokio::time::sleep(Duration::from_millis(100)).await; | ||
} | ||
} | ||
|
||
async fn receiver(mut rx: mpsc::Receiver<u32>, count: u32) { | ||
info!("rx: started"); | ||
|
||
for _ in 0..count { | ||
let msg = rx.recv().await; | ||
info!("rx: Received message: '{:?}'", msg); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.