Differences between: sysbench-0.4.12 (suffix '.orig') and sysbench-0.4.12 diff -upN sysbench-0.4.12/sysbench/sb_timer.c.orig sysbench-0.4.12/sysbench/sb_timer.c --- sysbench-0.4.12/sysbench/sb_timer.c.orig 2009-03-15 12:42:04.000000000 +0000 +++ sysbench-0.4.12/sysbench/sb_timer.c 2009-04-03 22:30:40.646057000 +0000 @@ -192,3 +192,44 @@ sb_timer_t merge_timers(sb_timer_t *t1, return t; } + + +/* Subtract *before from *after. Result given via pointer *diff. */ + + +void +diff_tv(long long *diff, struct timespec *before, struct timespec *after) +{ + time_t sec; + + sec = after->tv_sec - before->tv_sec; + if (sec != 0) + *diff = sec * 1000000000LL + after->tv_nsec - before->tv_nsec; + else + *diff = after->tv_nsec - before->tv_nsec; +} + + +/* Add a number of nanoseconds to a struct timespec */ + + +void +add_ns_to_timespec(struct timespec *dest, long long *delta) +{ + long long x; + time_t sec; + + x = dest->tv_nsec + *delta; + if (x > 1000000000) { + /* Future second */ + dest->tv_sec += x / 1000000000; + dest->tv_nsec = x % 1000000000; + } else if (x < 0) { + /* Past second */ + dest->tv_sec = dest->tv_sec - 1 + (x / 1000000000); + dest->tv_nsec = (x % 1000000000) + 1000000000; + } else { + /* Within the same second */ + dest->tv_nsec = x; + } +} diff -upN sysbench-0.4.12/sysbench/sb_timer.h.orig sysbench-0.4.12/sysbench/sb_timer.h --- sysbench-0.4.12/sysbench/sb_timer.h.orig 2009-03-15 12:42:04.000000000 +0000 +++ sysbench-0.4.12/sysbench/sb_timer.h 2009-04-01 21:36:50.000000000 +0000 @@ -107,4 +107,10 @@ unsigned long long get_max_time(sb_time /* sum data from two timers. used in summing data from multiple threads */ sb_timer_t merge_timers(sb_timer_t *, sb_timer_t *); +/* subtract *after from *before */ +void diff_tv(long long *diff, struct timespec *before, struct timespec *after); + +/* add a number of nanoseconds to a struct timespec */ +void add_ns_to_timespec(struct timespec *dest, long long *delta); + #endif /* SB_TIMER_H */ diff -upN sysbench-0.4.12/sysbench/sysbench.c.orig sysbench-0.4.12/sysbench/sysbench.c --- sysbench-0.4.12/sysbench/sysbench.c.orig 2009-03-19 14:37:08.000000000 +0000 +++ sysbench-0.4.12/sysbench/sysbench.c 2009-04-01 21:46:00.000000000 +0000 @@ -75,6 +75,9 @@ static int thread_stack_size; sb_arg_t general_args[] = { {"num-threads", "number of threads to use", SB_ARG_TYPE_INT, "1"}, + {"tx-rate", "target transaction rate", SB_ARG_TYPE_INT, "0"}, + {"tx-jitter", "target transaction variation, in microseconds", + SB_ARG_TYPE_INT, "0"}, {"max-requests", "limit for total number of requests", SB_ARG_TYPE_INT, "10000"}, {"max-time", "limit for total execution time in seconds", SB_ARG_TYPE_INT, "0"}, {"forced-shutdown", "amount of time to wait after --max-time before forcing shutdown", @@ -332,6 +335,9 @@ void print_run_mode(sb_test_t *test) { log_text(LOG_NOTICE, "Running the test with following options:"); log_text(LOG_NOTICE, "Number of threads: %d", sb_globals.num_threads); + if (sb_globals.tx_rate > 0) + log_text(LOG_NOTICE, "Target transaction rate: %d/sec", + sb_globals.tx_rate); if (sb_globals.debug) log_text(LOG_NOTICE, "Debug mode enabled.\n"); @@ -363,6 +369,8 @@ void *runner_thread(void *arg) sb_thread_ctxt_t *ctxt; sb_test_t *test; unsigned int thread_id; + long long period_ns, pause_ns, jitter_ns; + struct timespec target_tv, now_tv, wakeup_tv; ctxt = (sb_thread_ctxt_t *)arg; test = ctxt->test; @@ -374,13 +382,36 @@ void *runner_thread(void *arg) sb_globals.error = 1; return NULL; /* thread initialization failed */ } - + + if (sb_globals.tx_rate > 0) + { + /* initialize tx_rate variables */ + period_ns = (long long) round(1000000000.0 / sb_globals.tx_rate * + sb_globals.num_threads); + if (sb_globals.tx_jitter > 0) + jitter_ns = sb_globals.tx_jitter * 1000; + else + /* Default jitter is 1/10th of the period */ + jitter_ns = period_ns / 10; + } + /* We do this to make sure all threads get to this barrier about the same time */ pthread_mutex_lock(&thread_start_mutex); pthread_mutex_unlock(&thread_start_mutex); + + if (sb_globals.tx_rate > 0) + { + /* we are time-rating transactions */ + SB_GETTIME(&target_tv); + /* For the first transaction - ramp up */ + pause_ns = period_ns / sb_globals.num_threads * thread_id; + add_ns_to_timespec(&target_tv, &period_ns); + usleep(pause_ns / 1000); + } + do { request = get_request(test, thread_id); @@ -398,6 +429,18 @@ void *runner_thread(void *arg) log_text(LOG_INFO, "Time limit exceeded, exiting..."); break; } + + /* check if we are time-rating transactions and need to pause */ + if (sb_globals.tx_rate > 0) + { + add_ns_to_timespec(&target_tv, &period_ns); + SB_GETTIME(&now_tv); + diff_tv(&pause_ns, &now_tv, &target_tv); + pause_ns = pause_ns - (jitter_ns / 2) + (lrand48() % jitter_ns); + if (pause_ns > 5000) + usleep(pause_ns / 1000); + } + } while ((request.type != SB_REQ_TYPE_NULL) && (!sb_globals.error) ); if (test->ops.thread_done != NULL) @@ -543,6 +586,8 @@ int init(void) log_text(LOG_FATAL, "Invalid value for --num-threads: %d.\n", sb_globals.num_threads); return 1; } + sb_globals.tx_rate = sb_get_value_int("tx-rate"); + sb_globals.tx_jitter = sb_get_value_int("tx-jitter"); sb_globals.max_requests = sb_get_value_int("max-requests"); sb_globals.max_time = sb_get_value_int("max-time"); if (!sb_globals.max_requests && !sb_globals.max_time) diff -upN sysbench-0.4.12/sysbench/sysbench.h.orig sysbench-0.4.12/sysbench/sysbench.h --- sysbench-0.4.12/sysbench/sysbench.h.orig 2009-03-19 08:36:25.000000000 +0000 +++ sysbench-0.4.12/sysbench/sysbench.h 2009-04-01 21:42:02.000000000 +0000 @@ -188,6 +188,8 @@ typedef struct pthread_mutex_t exec_mutex; /* execution mutex */ sb_timer_t *op_timers; /* timers to measure each thread's run time */ sb_timer_t exec_timer; /* total execution timer */ + unsigned int tx_rate; /* target transaction rate */ + unsigned int tx_jitter; /* target transaction variation (us) */ unsigned int num_threads; /* number of threads to use */ unsigned int max_requests; /* maximum number of requests */ unsigned int max_time; /* total execution time limit */