diff options
Diffstat (limited to 'src/third_party/wiredtiger/bench/wtperf/wtperf_throttle.c')
-rw-r--r-- | src/third_party/wiredtiger/bench/wtperf/wtperf_throttle.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/third_party/wiredtiger/bench/wtperf/wtperf_throttle.c b/src/third_party/wiredtiger/bench/wtperf/wtperf_throttle.c new file mode 100644 index 00000000000..bba1f629715 --- /dev/null +++ b/src/third_party/wiredtiger/bench/wtperf/wtperf_throttle.c @@ -0,0 +1,121 @@ +/*- + * Public Domain 2014-2015 MongoDB, Inc. + * Public Domain 2008-2014 WiredTiger, Inc. + * + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "wtperf.h" + +/* + * Put the initial config together for running a throttled workload. + */ +int +setup_throttle(CONFIG_THREAD *thread) +{ + THROTTLE_CONFIG *throttle_cfg; + + throttle_cfg = &thread->throttle_cfg; + + /* + * Setup how the number of operations to run each interval in order to + * meet our desired max throughput. + * - If we have a very small number of them we can do one op + * on a larger increment. Given there is overhead in throttle logic + * we want to avoid running the throttle check regularly. + * - For most workloads, we aim to do 100 ops per interval and adjust + * the sleep period accordingly. + * - For high throughput workloads, we aim to do many ops in 100us + * increments. + */ + + if (thread->workload->throttle < THROTTLE_OPS) { + /* If the interval is very small, we do one operation */ + throttle_cfg->usecs_increment = + USEC_PER_SEC / thread->workload->throttle; + throttle_cfg->ops_per_increment = 1; + } else if (thread->workload->throttle < USEC_PER_SEC / THROTTLE_OPS) { + throttle_cfg->usecs_increment = + USEC_PER_SEC / thread->workload->throttle * THROTTLE_OPS; + throttle_cfg->ops_per_increment = THROTTLE_OPS; + } else { + /* If the interval is large, we do more ops per interval */ + throttle_cfg->usecs_increment = USEC_PER_SEC / THROTTLE_OPS; + throttle_cfg->ops_per_increment = + thread->workload->throttle / THROTTLE_OPS; + } + + /* Give the queue some initial operations to work with */ + throttle_cfg->ops_count = throttle_cfg->ops_per_increment; + + /* Set the first timestamp of when we incremented */ + WT_RET(__wt_epoch(NULL, &throttle_cfg->last_increment)); + return (0); +} + +/* + * Run the throttle function. We will sleep if needed and then reload the + * counter to perform more operations. + */ +int +worker_throttle(CONFIG_THREAD *thread) +{ + THROTTLE_CONFIG *throttle_cfg; + struct timespec now; + uint64_t usecs_delta; + + throttle_cfg = &thread->throttle_cfg; + + WT_RET(__wt_epoch(NULL, &now)); + + /* + * If we did enough operations in the current interval, sleep for + * the rest of the interval. Then add more operations to the queue. + */ + usecs_delta = WT_TIMEDIFF_US(now, throttle_cfg->last_increment); + if (usecs_delta < throttle_cfg->usecs_increment) { + (void)usleep( + (useconds_t)(throttle_cfg->usecs_increment - usecs_delta)); + throttle_cfg->ops_count = + throttle_cfg->ops_per_increment; + /* + * After sleeping, set the interval to the current time. + */ + WT_RET(__wt_epoch(NULL, &throttle_cfg->last_increment)); + } else { + throttle_cfg->ops_count = + (uint64_t) (float)(usecs_delta / + throttle_cfg->usecs_increment) * + (float)throttle_cfg->ops_per_increment; + throttle_cfg->last_increment = now; + } + + /* + * Take the minimum so we don't overfill the queue. + */ + throttle_cfg->ops_count = + WT_MIN(throttle_cfg->ops_count, thread->workload->throttle); + + return (0); +} |