From 97c5373fc72c7324314709111cb9d226d8b4d70b Mon Sep 17 00:00:00 2001 From: Maciej Szwed Date: Wed, 21 Apr 2021 10:36:15 +0200 Subject: [PATCH] test/scheduler: make activity of a thread % of time period So far the test application was mostly used for cases with single active thread on a core. Setting activity as percentage of all poller operations worked fine for those cases. This patch changes the thread activity to mean percentage of a set time period. Which equals to the maximum load a thread will see when being alone on the core. Right now g_core_time_period is set to 100ms, and is the maximum execution time for all threads on a core when thread activity is set to 100%. g_timeslice is set to 100us and is the execution time of single thread poll. Consider following scenario: Before the patch Thread1 Activity 70% Busy 70 Idle 30 Load 70% Thread2 Activity 60% Busy 60 Idle 40 Load 60% Core Busy 130 Idle 70 Load 65% After the patch Thread1 Activity 70% Busy 100 Idle 0 Load 100% Thread2 Activity 60% Busy 100 Idle 0 Load 100% Core Busy 200 Idle 0 Load 100% Additionally increased period of sleeping from 1us to 100us, to offset the time needed for additional operations during thread poll. Signed-off-by: Tomasz Zawadzki Signed-off-by: Maciej Szwed Change-Id: I027432db1bea570dd58829eeccf7dd8bb06bf249 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7474 Tested-by: SPDK CI Jenkins Community-CI: Broadcom CI Reviewed-by: Paul Luse Reviewed-by: Krzysztof Karas Reviewed-by: Shuhei Matsumoto Reviewed-by: Ben Walker --- test/event/scheduler/scheduler.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/test/event/scheduler/scheduler.c b/test/event/scheduler/scheduler.c index b50523192..840b69028 100644 --- a/test/event/scheduler/scheduler.c +++ b/test/event/scheduler/scheduler.c @@ -45,11 +45,16 @@ static bool g_is_running = true; pthread_mutex_t g_sched_list_mutex = PTHREAD_MUTEX_INITIALIZER; +#define TIMESLICE_US 100 /* Execution time of single busy thread poll in us. */ +static uint64_t g_core_time_period; +static uint64_t g_timeslice_tsc; struct sched_thread { struct spdk_thread *thread; struct spdk_poller *poller; int active_percent; + uint64_t next_period_tsc; + uint64_t remaining_tsc; struct spdk_jsonrpc_request *request; TAILQ_ENTRY(sched_thread) link; }; @@ -99,12 +104,11 @@ thread_delete(struct sched_thread *sched_thread) } } -static __thread unsigned int seed = 0; - static int poller_run(void *arg) { struct sched_thread *sched_thread = arg; + uint64_t now; if (spdk_unlikely(!g_is_running)) { pthread_mutex_lock(&g_sched_list_mutex); @@ -113,10 +117,17 @@ poller_run(void *arg) return SPDK_POLLER_IDLE; } - spdk_delay_us(1); + now = spdk_get_ticks(); - if ((sched_thread->active_percent == 100) || - (sched_thread->active_percent != 0 && (rand_r(&seed) % 100) < sched_thread->active_percent)) { + /* Reset the timers once we go over single core time period */ + if (sched_thread->next_period_tsc <= now) { + sched_thread->next_period_tsc = now + g_core_time_period; + sched_thread->remaining_tsc = (g_core_time_period / 100) * sched_thread->active_percent; + } + + if (sched_thread->remaining_tsc > 0) { + spdk_delay_us(TIMESLICE_US); + sched_thread->remaining_tsc -= spdk_min(sched_thread->remaining_tsc, g_timeslice_tsc); return SPDK_POLLER_BUSY; } @@ -184,6 +195,7 @@ rpc_scheduler_thread_create(struct spdk_jsonrpc_request *request, sched_thread->request = request; sched_thread->active_percent = req.active_percent; + sched_thread->next_period_tsc = 0; spdk_thread_send_msg(sched_thread->thread, rpc_register_poller, sched_thread); @@ -225,6 +237,8 @@ rpc_scheduler_thread_set_active_cb(void *arg) pthread_mutex_lock(&g_sched_list_mutex); TAILQ_FOREACH(sched_thread, &g_sched_threads, link) { if (spdk_thread_get_id(sched_thread->thread) == thread_id) { + /* Reset next_period_tsc to force recalculation of remaining_tsc. */ + sched_thread->next_period_tsc = 0; sched_thread->active_percent = ctx->active_percent; pthread_mutex_unlock(&g_sched_list_mutex); spdk_jsonrpc_send_bool_response(ctx->request, true); @@ -367,6 +381,11 @@ test_shutdown(void) static void test_start(void *arg1) { + /* Hardcode g_core_time_period as 100ms. */ + g_core_time_period = spdk_get_ticks_hz() / 10; + /* Hardcode g_timeslice_tsc as 100us. */ + g_timeslice_tsc = spdk_get_ticks_hz() / SPDK_SEC_TO_USEC * TIMESLICE_US; + SPDK_NOTICELOG("Scheduler test application started.\n"); }