From 45830f9cd02b01ed3e91ea74f9403e4ffb2c0562 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sun, 22 Jan 2017 10:45:08 +0300 Subject: [PATCH] Optimizations and cleanups around sb_next_event(). --- sysbench/lua/internal/sysbench.lua | 4 +- sysbench/sb_lua.c | 33 ------------- sysbench/sysbench.c | 74 ++++++++++++++++------------- sysbench/sysbench.h | 22 +++++---- sysbench/tests/cpu/sb_cpu.c | 19 +------- sysbench/tests/fileio/sb_fileio.c | 16 +++++-- sysbench/tests/memory/sb_memory.c | 7 ++- sysbench/tests/threads/sb_threads.c | 17 ++----- 8 files changed, 78 insertions(+), 114 deletions(-) diff --git a/sysbench/lua/internal/sysbench.lua b/sysbench/lua/internal/sysbench.lua index 110b8b0..46d0973 100644 --- a/sysbench/lua/internal/sysbench.lua +++ b/sysbench/lua/internal/sysbench.lua @@ -19,7 +19,7 @@ ffi = require("ffi") ffi.cdef[[ void sb_event_start(int thread_id); void sb_event_stop(int thread_id); -bool sb_lua_more_events(int thread_id); +bool sb_more_events(int thread_id); ]] -- ---------------------------------------------------------------------- @@ -28,7 +28,7 @@ bool sb_lua_more_events(int thread_id); function thread_run(thread_id) local success, ret - while ffi.C.sb_lua_more_events(thread_id) do + while ffi.C.sb_more_events(thread_id) do ffi.C.sb_event_start(thread_id) repeat diff --git a/sysbench/sb_lua.c b/sysbench/sb_lua.c index ed086e1..f7356e9 100644 --- a/sysbench/sb_lua.c +++ b/sysbench/sb_lua.c @@ -97,9 +97,6 @@ bool sb_lua_more_events(int); static lua_State **states CK_CC_CACHELINE; -/* Event counter */ -static unsigned int nevents CK_CC_CACHELINE; - static sb_test_t sbtest CK_CC_CACHELINE; static const char *sb_lua_script_path CK_CC_CACHELINE; @@ -124,7 +121,6 @@ static lua_State *gstate; static int sb_lua_op_init(void); static int sb_lua_op_done(void); -static sb_event_t sb_lua_next_event(int); static int sb_lua_op_thread_init(int); static int sb_lua_op_thread_run(int); static int sb_lua_op_thread_done(int); @@ -132,7 +128,6 @@ static void sb_lua_op_print_stats(sb_stat_t type); static sb_operations_t lua_ops = { .init = sb_lua_op_init, - .next_event = &sb_lua_next_event, .done = sb_lua_op_done }; @@ -264,24 +259,6 @@ int sb_lua_op_init(void) return 0; } -sb_event_t sb_lua_next_event(int thread_id) -{ - sb_event_t req; - - (void) thread_id; /* unused */ - - if (sb_globals.max_requests > 0 && - ck_pr_faa_uint(&nevents, 1) >= sb_globals.max_requests) - { - req.type = SB_REQ_TYPE_NULL; - return req; - } - - req.type = SB_REQ_TYPE_SCRIPT; - - return req; -} - int sb_lua_op_thread_init(int thread_id) { lua_State * L; @@ -1070,16 +1047,6 @@ unsigned int sb_lua_table_size(lua_State *L, int index) return i; } -/* Check if there are more events to execute */ - -bool sb_lua_more_events(int thread_id) -{ - sb_event_t e; - - e = sb_next_event(&sbtest, thread_id); - return e.type == SB_REQ_TYPE_SCRIPT; -} - /* Check if a specified hook exists */ bool sb_lua_hook_defined(lua_State *L, const char *name) diff --git a/sysbench/sysbench.c b/sysbench/sysbench.c index 3d1c274..f62b0b7 100644 --- a/sysbench/sysbench.c +++ b/sysbench/sysbench.c @@ -152,9 +152,6 @@ static int report_thread_created; static int checkpoints_thread_created; static int eventgen_thread_created; -/* Time limit (--max-time) in nanoseconds */ -static uint64_t max_time_ns CK_CC_CACHELINE; - /* Global execution timer */ sb_timer_t sb_exec_timer CK_CC_CACHELINE; @@ -412,7 +409,7 @@ void print_run_mode(sb_test_t *test) if (sb_globals.force_shutdown) log_text(LOG_NOTICE, "Forcing shutdown in %u seconds", - sb_globals.max_time + sb_globals.timeout); + (unsigned) NS2SEC(sb_globals.max_time_ns) + sb_globals.timeout); log_text(LOG_NOTICE, ""); @@ -420,6 +417,29 @@ void print_run_mode(sb_test_t *test) test->ops.print_mode(); } +bool sb_more_events(int thread_id) +{ + (void) thread_id; /* unused */ + + if (sb_globals.error) + return false; + + /* Check if we have a time limit */ + if (sb_globals.max_time_ns > 0 && + sb_timer_value(&sb_exec_timer) >= sb_globals.max_time_ns) + { + log_text(LOG_INFO, "Time limit exceeded, exiting..."); + return false; + } + + /* Check if we have a limit on the number of events */ + if (sb_globals.max_requests > 0 && + ck_pr_faa_64(&sb_globals.nevents, 1) >= sb_globals.max_requests) + return false; + + return true; +} + /* Get the next event, or return an 'empty' event with type = SB_REQ_TYPE_NULL, if there are no more events to execute. @@ -427,30 +447,20 @@ void print_run_mode(sb_test_t *test) sb_event_t sb_next_event(sb_test_t *test, int thread_id) { - sb_event_t event; sb_list_item_t *pos; event_queue_elem_t *elem; unsigned long long queue_start_time = 0; - event.type = SB_REQ_TYPE_NULL; - - if (sb_globals.error) - return event; - - /* Check if we have a time limit */ - if (max_time_ns > 0 && - sb_timer_value(&sb_exec_timer) >= max_time_ns) - { - log_text(LOG_INFO, "Time limit exceeded, exiting..."); - return event; - } - /* If we are in tx_rate mode, we take events from queue */ if (sb_globals.tx_rate > 0) { if (queue_is_full) { log_text(LOG_FATAL, "Event queue is full."); + + sb_event_t event; + event.type = SB_REQ_TYPE_NULL; + return event; } pthread_mutex_lock(&event_queue_mutex); @@ -476,9 +486,7 @@ sb_event_t sb_next_event(sb_test_t *test, int thread_id) } - event = test->ops.next_event(thread_id); - - return event; + return test->ops.next_event(thread_id); } @@ -524,9 +532,12 @@ static int thread_run(sb_test_t *test, int thread_id) sb_event_t event; int rc = 0; - while ((event = sb_next_event(test, thread_id)).type != SB_REQ_TYPE_NULL && - rc == 0) + while (sb_more_events(thread_id) && rc == 0) { + event = sb_next_event(test, thread_id); + if (event.type == SB_REQ_TYPE_NULL) + break; + sb_event_start(thread_id); rc = test->ops.execute_event(&event, thread_id); @@ -934,7 +945,7 @@ static int run_test(sb_test_t *test) /* Set the alarm to force shutdown */ signal(SIGALRM, sigalrm_forced_shutdown_handler); - alarm(sb_globals.max_time + sb_globals.timeout); + alarm(NS2SEC(sb_globals.max_time_ns) + sb_globals.timeout); } #endif @@ -1044,30 +1055,29 @@ static int init(void) return 1; } sb_globals.max_requests = sb_get_value_int("max-requests"); - sb_globals.max_time = sb_get_value_int("max-time"); - max_time_ns = SEC2NS(sb_globals.max_time); + sb_globals.max_time_ns = SEC2NS(sb_get_value_int("max-time")); - if (!sb_globals.max_requests && !sb_globals.max_time) + if (!sb_globals.max_requests && !sb_globals.max_time_ns) log_text(LOG_WARNING, "WARNING: Both max-requests and max-time are 0, running endless test"); - if (sb_globals.max_time > 0) + if (sb_globals.max_time_ns > 0) { /* Parse the --forced-shutdown value */ tmp = sb_get_value_string("forced-shutdown"); if (tmp == NULL) { sb_globals.force_shutdown = 1; - sb_globals.timeout = sb_globals.max_time / 20; + sb_globals.timeout = NS2SEC(sb_globals.max_time_ns) / 20; } else if (strcasecmp(tmp, "off")) { char *endptr; sb_globals.force_shutdown = 1; - sb_globals.timeout = (unsigned int)strtol(tmp, &endptr, 10); + sb_globals.timeout = (unsigned) strtol(tmp, &endptr, 10); if (*endptr == '%') - sb_globals.timeout = (unsigned int)(sb_globals.timeout * - (double)sb_globals.max_time / 100); + sb_globals.timeout = (unsigned) (sb_globals.timeout * + NS2SEC(sb_globals.max_time_ns) / 100); else if (*tmp == '\0' || *endptr != '\0') { log_text(LOG_FATAL, "Invalid value for --forced-shutdown: '%s'", tmp); diff --git a/sysbench/sysbench.h b/sysbench/sysbench.h index 6ffe276..1084fab 100644 --- a/sysbench/sysbench.h +++ b/sysbench/sysbench.h @@ -1,5 +1,5 @@ /* Copyright (C) 2004 MySQL AB - Copyright (C) 2004-2016 Alexey Kopytov + Copyright (C) 2004-2017 Alexey Kopytov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -180,10 +180,13 @@ typedef struct typedef struct { + int error CK_CC_CACHELINE; /* global error flag */ + unsigned int tx_rate; /* target transaction rate */ + unsigned int max_requests; /* maximum number of requests */ + unsigned int max_time_ns; /* total execution time limit */ + pthread_mutex_t exec_mutex CK_CC_CACHELINE; /* execution mutex */ sb_cmd_t command; /* command passed from command line */ - int error; /* global error - everyone exit */ - pthread_mutex_t exec_mutex; /* execution mutex */ - unsigned int num_threads; /* number of threads to use */ + unsigned int num_threads CK_CC_CACHELINE; /* number of threads to use */ unsigned int num_running; /* number of threads currently active */ unsigned int report_interval; /* intermediate reports interval */ unsigned int percentile; /* percentile rank for latency stats */ @@ -191,11 +194,7 @@ typedef struct /* array of report checkpoints */ unsigned int checkpoints[MAX_CHECKPOINTS]; unsigned int n_checkpoints; /* number of checkpoints */ - unsigned int tx_rate; /* target transaction rate */ - unsigned int max_requests; /* maximum number of requests */ - unsigned int max_time; /* total execution time limit */ unsigned char debug; /* debug flag */ - int force_shutdown; /* whether we must force test shutdown */ unsigned int timeout; /* forced shutdown timeout */ unsigned char validate; /* validation flag */ unsigned char verbosity; /* log verbosity */ @@ -204,11 +203,13 @@ typedef struct int concurrency; /* number of concurrent requests when tx-rate is used */ /* 1 when forced shutdown is in progress, 0 otherwise */ + int force_shutdown; /* whether we must force test shutdown */ int forced_shutdown_in_progress; + uint64_t nevents CK_CC_CACHELINE; /* event counter */ } sb_globals_t; -extern sb_globals_t sb_globals; -extern pthread_mutex_t event_queue_mutex; +extern sb_globals_t sb_globals CK_CC_CACHELINE; +extern pthread_mutex_t event_queue_mutex CK_CC_CACHELINE; /* Global execution timer */ extern sb_timer_t sb_exec_timer CK_CC_CACHELINE; @@ -220,6 +221,7 @@ extern sb_timer_t sb_checkpoint_timer2; extern TLS int sb_tls_thread_id; +bool sb_more_events(int thread_id); sb_event_t sb_next_event(sb_test_t *test, int thread_id); void sb_event_start(int thread_id); void sb_event_stop(int thread_id); diff --git a/sysbench/tests/cpu/sb_cpu.c b/sysbench/tests/cpu/sb_cpu.c index 9c2d479..9f3ba29 100644 --- a/sysbench/tests/cpu/sb_cpu.c +++ b/sysbench/tests/cpu/sb_cpu.c @@ -1,5 +1,5 @@ /* Copyright (C) 2004 MySQL AB - Copyright (C) 2004-2016 Alexey Kopytov + Copyright (C) 2004-2017 Alexey Kopytov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -59,8 +59,6 @@ static sb_test_t cpu_test = /* Upper limit for primes */ static unsigned int max_prime; -/* Request counter */ -static unsigned int req_performed; int register_test_cpu(sb_list_t * tests) { @@ -79,8 +77,6 @@ int cpu_init(void) } max_prime= (unsigned int)prime_option; - req_performed = 0; - return 0; } @@ -91,19 +87,6 @@ sb_event_t cpu_next_event(int thread_id) (void) thread_id; /* unused */ - if (sb_globals.max_requests > 0) - { - SB_THREAD_MUTEX_LOCK(); - if (req_performed >= sb_globals.max_requests) - { - req.type = SB_REQ_TYPE_NULL; - SB_THREAD_MUTEX_UNLOCK(); - return req; - } - req_performed++; - SB_THREAD_MUTEX_UNLOCK(); - } - req.type = SB_REQ_TYPE_CPU; return req; diff --git a/sysbench/tests/fileio/sb_fileio.c b/sysbench/tests/fileio/sb_fileio.c index 16b3e13..9fc2f9b 100644 --- a/sysbench/tests/fileio/sb_fileio.c +++ b/sysbench/tests/fileio/sb_fileio.c @@ -27,6 +27,7 @@ #ifdef STDC_HEADERS # include # include +# include #endif #ifdef HAVE_UNISTD_H @@ -199,6 +200,9 @@ static FILE_DESCRIPTOR *files; /* test mode type */ static file_test_mode_t test_mode; +/* Limit on the number of events */ +static uint64_t max_events; + /* Previous request needed for validation */ static sb_file_request_t prev_req; @@ -331,6 +335,10 @@ int file_init(void) init_vars(); clear_stats(); + /* Use our own limit on the number of events */ + max_events = sb_globals.max_requests; + sb_globals.max_requests = 0; + return 0; } @@ -433,7 +441,7 @@ sb_event_t file_get_seq_request(void) file_req->operation = FILE_OP_TYPE_READ; /* Do final fsync on all files and quit if we are done */ - if (sb_globals.max_requests > 0 && req_performed >= sb_globals.max_requests) + if (max_events > 0 && req_performed >= max_events) { /* no fsync for reads */ if (file_fsync_end && file_req->operation == FILE_OP_TYPE_WRITE && @@ -548,7 +556,7 @@ sb_event_t file_get_rnd_request(int thread_id) } /* fsync all files (if requested by user) as soon as we are done */ - if (sb_globals.max_requests > 0 && req_performed >= sb_globals.max_requests) + if (max_events > 0 && req_performed >= max_events) { if (file_fsync_end != 0 && (real_mode == MODE_RND_WRITE || real_mode == MODE_RND_RW || @@ -788,8 +796,8 @@ void file_print_mode(void) case MODE_RND_WRITE: case MODE_RND_READ: case MODE_RND_RW: - log_text(LOG_NOTICE, "Number of IO requests: %d", - sb_globals.max_requests); + log_text(LOG_NOTICE, "Number of IO requests: %" PRIu64, + max_events); log_text(LOG_NOTICE, "Read/Write ratio for combined random IO test: %2.2f", file_rw_ratio); diff --git a/sysbench/tests/memory/sb_memory.c b/sysbench/tests/memory/sb_memory.c index cbc9012..764f61e 100644 --- a/sysbench/tests/memory/sb_memory.c +++ b/sysbench/tests/memory/sb_memory.c @@ -1,5 +1,5 @@ /* Copyright (C) 2004 MySQL AB - Copyright (C) 2004-2016 Alexey Kopytov + Copyright (C) 2004-2017 Alexey Kopytov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -201,7 +201,10 @@ int memory_init(void) memset(buffers[i], 0, memory_block_size); } } - + + /* Use our own limit on the number of events */ + sb_globals.max_requests = 0; + return 0; } diff --git a/sysbench/tests/threads/sb_threads.c b/sysbench/tests/threads/sb_threads.c index 462c952..d224017 100644 --- a/sysbench/tests/threads/sb_threads.c +++ b/sysbench/tests/threads/sb_threads.c @@ -1,5 +1,5 @@ /* Copyright (C) 2004 MySQL AB - Copyright (C) 2004-2016 Alexey Kopytov + Copyright (C) 2004-2017 Alexey Kopytov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +29,7 @@ #endif #include "sysbench.h" +#include "ck_pr.h" /* How to test scheduler pthread_yield or sched_yield */ #ifdef HAVE_PTHREAD_YIELD @@ -92,7 +93,7 @@ int threads_init(void) thread_yields = sb_get_value_int("thread-yields"); thread_locks = sb_get_value_int("thread-locks"); req_performed = 0; - + return 0; } @@ -135,18 +136,8 @@ sb_event_t threads_next_event(int thread_id) (void) thread_id; /* unused */ - SB_THREAD_MUTEX_LOCK(); - if (sb_globals.max_requests > 0 && req_performed >= sb_globals.max_requests) - { - sb_req.type = SB_REQ_TYPE_NULL; - SB_THREAD_MUTEX_UNLOCK(); - return sb_req; - } - sb_req.type = SB_REQ_TYPE_THREADS; - threads_req->lock_num = req_performed % thread_locks; - req_performed++; - SB_THREAD_MUTEX_UNLOCK(); + threads_req->lock_num = ck_pr_faa_uint(&req_performed, 1) % thread_locks; return sb_req; }