D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
sbin
/
Filename :
runqlat.bt
back
Copy
#!/usr/bin/env bpftrace // runqlat.bt CPU scheduler run queue latency as a histogram. // For Linux, uses bpftrace, eBPF. // // Example of usage: // // # ./runqlat.bt // Attaching 5 probes... // Tracing CPU scheduler... Hit Ctrl-C to end. // ^C // // // // @usecs: // [0] 1 | | // [1] 11 |@@ | // [2, 4) 16 |@@@ | // [4, 8) 43 |@@@@@@@@@@ | // [8, 16) 134 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | // [16, 32) 220 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| // [32, 64) 117 |@@@@@@@@@@@@@@@@@@@@@@@@@@@ | // [64, 128) 84 |@@@@@@@@@@@@@@@@@@@ | // [128, 256) 10 |@@ | // [256, 512) 2 | | // [512, 1K) 5 |@ | // [1K, 2K) 5 |@ | // [2K, 4K) 5 |@ | // [4K, 8K) 4 | | // [8K, 16K) 1 | | // [16K, 32K) 2 | | // [32K, 64K) 0 | | // [64K, 128K) 1 | | // [128K, 256K) 0 | | // [256K, 512K) 0 | | // [512K, 1M) 1 | | // // This is an idle system where most of the time we are waiting for less than // 128 microseconds, shown by the mode above. As an example of reading the output, // the above histogram shows 220 scheduling events with a run queue latency of // between 16 and 32 microseconds. // // The output also shows an outlier taking between 0.5 and 1 seconds: ??? XXX // likely work was scheduled behind another higher priority task, and had to wait // briefly. The kernel decides whether it is worth migrating such work to an // idle CPU, or leaving it wait its turn on its current CPU run queue where // the CPU caches should be hotter. // // // I'll now add a single-threaded CPU bound workload to this system, and bind // it on one CPU: // // # ./runqlat.bt // Attaching 5 probes... // Tracing CPU scheduler... Hit Ctrl-C to end. // ^C // // // // @usecs: // [1] 6 |@@@ | // [2, 4) 26 |@@@@@@@@@@@@@ | // [4, 8) 97 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| // [8, 16) 72 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | // [16, 32) 17 |@@@@@@@@@ | // [32, 64) 19 |@@@@@@@@@@ | // [64, 128) 20 |@@@@@@@@@@ | // [128, 256) 3 |@ | // [256, 512) 0 | | // [512, 1K) 0 | | // [1K, 2K) 1 | | // [2K, 4K) 1 | | // [4K, 8K) 4 |@@ | // [8K, 16K) 3 |@ | // [16K, 32K) 0 | | // [32K, 64K) 0 | | // [64K, 128K) 0 | | // [128K, 256K) 1 | | // [256K, 512K) 0 | | // [512K, 1M) 0 | | // [1M, 2M) 1 | | // // That didn't make much difference. // // // Now I'll add a second single-threaded CPU workload, and bind it to the same // CPU, causing contention: // // # ./runqlat.bt // Attaching 5 probes... // Tracing CPU scheduler... Hit Ctrl-C to end. // ^C // // // // @usecs: // [0] 1 | | // [1] 8 |@@@ | // [2, 4) 28 |@@@@@@@@@@@@ | // [4, 8) 95 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | // [8, 16) 120 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| // [16, 32) 22 |@@@@@@@@@ | // [32, 64) 10 |@@@@ | // [64, 128) 7 |@@@ | // [128, 256) 3 |@ | // [256, 512) 1 | | // [512, 1K) 0 | | // [1K, 2K) 0 | | // [2K, 4K) 2 | | // [4K, 8K) 4 |@ | // [8K, 16K) 107 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | // [16K, 32K) 0 | | // [32K, 64K) 0 | | // [64K, 128K) 0 | | // [128K, 256K) 0 | | // [256K, 512K) 1 | | // // There's now a second mode between 8 and 16 milliseconds, as each thread must // wait its turn on the one CPU. // // // Now I'll run 10 CPU-bound threads on one CPU: // // # ./runqlat.bt // Attaching 5 probes... // Tracing CPU scheduler... Hit Ctrl-C to end. // ^C // // // // @usecs: // [0] 2 | | // [1] 10 |@ | // [2, 4) 38 |@@@@ | // [4, 8) 63 |@@@@@@ | // [8, 16) 106 |@@@@@@@@@@@ | // [16, 32) 28 |@@@ | // [32, 64) 13 |@ | // [64, 128) 15 |@ | // [128, 256) 2 | | // [256, 512) 2 | | // [512, 1K) 1 | | // [1K, 2K) 1 | | // [2K, 4K) 2 | | // [4K, 8K) 4 | | // [8K, 16K) 3 | | // [16K, 32K) 0 | | // [32K, 64K) 478 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| // [64K, 128K) 1 | | // [128K, 256K) 0 | | // [256K, 512K) 0 | | // [512K, 1M) 0 | | // [1M, 2M) 1 | | // // This shows that most of the time threads need to wait their turn, with the // largest mode between 32 and 64 milliseconds. // // This is a bpftrace version of the bcc tool of the same name. // The bcc version provides options to customize the output. // // Copyright 2018 Netflix, Inc. // // 17-Sep-2018 Brendan Gregg Created this. #ifndef BPFTRACE_HAVE_BTF #include <linux/sched.h> #else // With BTF providing types, full headers are not needed. // We only need to supply the preprocessor defines used in this script. // TASK_RUNNING is not arch-dependant and has not changed in the linux // git history (it is not part of the stable API though) #define TASK_RUNNING 0 #endif BEGIN { printf("Tracing CPU scheduler... Hit Ctrl-C to end.\n"); } tracepoint:sched:sched_wakeup, tracepoint:sched:sched_wakeup_new { @qtime[args.pid] = nsecs; } tracepoint:sched:sched_switch { if (args.prev_state == TASK_RUNNING) { @qtime[args.prev_pid] = nsecs; } // Ignore the idle task if (args.next_pid == 0) { return; } $ns = @qtime[args.next_pid]; if $ns { @usecs = hist((nsecs - $ns) / 1000); // Swallowing deletion failures as they are expected $ignore = delete(@qtime, args.next_pid); } } END { clear(@qtime); }