diff --git a/module/scheduler/dynamic/scheduler_dynamic.c b/module/scheduler/dynamic/scheduler_dynamic.c index cf663c77bd..54c24b93a6 100644 --- a/module/scheduler/dynamic/scheduler_dynamic.c +++ b/module/scheduler/dynamic/scheduler_dynamic.c @@ -40,6 +40,7 @@ #include "spdk/thread.h" #include "spdk_internal/event.h" #include "spdk/scheduler.h" +#include "spdk_internal/usdt.h" static uint32_t g_main_lcore; @@ -102,6 +103,8 @@ _move_thread(struct spdk_scheduler_thread_info *thread_info, uint32_t dst_core) uint8_t busy_pct = _busy_pct(src->busy, src->idle); uint64_t tsc; + SPDK_DTRACE_PROBE2(dynsched_move, thread_info, dst_core); + if (src == dst) { /* Don't modify stats if thread is already on that core. */ return; @@ -315,10 +318,13 @@ balance(struct spdk_scheduler_core_info *cores_info, uint32_t cores_count) int rc; bool busy_threads_present = false; + SPDK_DTRACE_PROBE1(dynsched_balance, cores_count); + SPDK_ENV_FOREACH_CORE(i) { g_cores[i].thread_count = cores_info[i].threads_count; g_cores[i].busy = cores_info[i].current_busy_tsc; g_cores[i].idle = cores_info[i].current_idle_tsc; + SPDK_DTRACE_PROBE2(dynsched_core_info, i, &cores_info[i]); } main_core = &g_cores[g_main_lcore]; diff --git a/scripts/bpf/sched.bt b/scripts/bpf/sched.bt new file mode 100644 index 0000000000..e941d2c3b5 --- /dev/null +++ b/scripts/bpf/sched.bt @@ -0,0 +1,62 @@ + +struct spdk_thread_stats { + uint64_t busy_tsc; + uint64_t idle_tsc; +}; + +struct spdk_scheduler_thread_info { + uint32_t lcore; + uint64_t thread_id; + /* Defining these as a 1-element array here allows us to + * create local variables for these members when accessing + * them which improves readability. + */ + struct spdk_thread_stats total_stats[1]; + struct spdk_thread_stats current_stats[1]; +}; + +struct spdk_scheduler_core_info { + uint64_t total_idle_tsc; + uint64_t total_busy_tsc; + uint64_t current_idle_tsc; + uint64_t current_busy_tsc; + uint32_t lcore; + uint32_t threads_count; + bool interrupt_mode; + struct spdk_scheduler_thread_info *thread_infos; +}; + +usdt:__EXE__:dynsched_move { + $info = (struct spdk_scheduler_thread_info *)arg1; + $stats = (struct spdk_thread_stats *)$info->current_stats; + if ($stats->busy_tsc > 0) { + $thread_pct = $stats->busy_tsc * 100 / ($stats->busy_tsc + $stats->idle_tsc); + $core_pct = $stats->busy_tsc * 100 / (@cores_busy_tsc[$info->lcore] + @cores_idle_tsc[$info->lcore]); + } else { + $thread_pct = 0; + $core_pct = 0; + } + printf("td:%2d old:%2d new:%2d td_busy:%2d% core_busy:%2d%\n", + $info->thread_id, $info->lcore, arg2, $thread_pct, $core_pct); +} + +usdt:__EXE__:dynsched_balance { + printf("\n"); + clear(@cores_busy_tsc); + clear(@cores_idle_tsc); + printf("Starting balance across %d cores\n", arg1); +} + +usdt:__EXE__:dynsched_core_info { + $info = (struct spdk_scheduler_core_info *)arg2; + $busy = $info->current_busy_tsc; + $idle = $info->current_idle_tsc; + if ($busy > 0) { + $pct = $busy * 100 / ($busy + $idle); + } else { + $pct = 0; + } + printf("core:%2d busy:%10d idle:%10d pct:%2d% td_count:%2d\n", arg1, $busy, $idle, $pct, $info->threads_count); + @cores_busy_tsc[arg1] = $busy; + @cores_idle_tsc[arg1] = $idle; +}