diff options
Diffstat (limited to 'bench/wtperf/wtperf.c')
-rw-r--r-- | bench/wtperf/wtperf.c | 134 |
1 files changed, 112 insertions, 22 deletions
diff --git a/bench/wtperf/wtperf.c b/bench/wtperf/wtperf.c index b2e68198e9a..340c400ba7e 100644 --- a/bench/wtperf/wtperf.c +++ b/bench/wtperf/wtperf.c @@ -33,6 +33,7 @@ static const CONFIG default_cfg = { "WT_TEST", /* home */ "WT_TEST", /* monitor dir */ NULL, /* partial logging */ + NULL, /* reopen config */ NULL, /* base_uri */ NULL, /* uris */ NULL, /* helium_mount */ @@ -59,7 +60,7 @@ static const CONFIG default_cfg = { 0, /* in warmup phase */ false, /* Signal for idle cycle thread */ 0, /* total seconds running */ - 0, /* has truncate */ + 0, /* flags */ {NULL, NULL}, /* the truncate queue */ {NULL, NULL}, /* the config queue */ @@ -86,6 +87,7 @@ static int start_threads(CONFIG *, WORKLOAD *, CONFIG_THREAD *, u_int, void *(*)(void *)); static int stop_threads(CONFIG *, u_int, CONFIG_THREAD *); static void *thread_run_wtperf(void *); +static void update_value_delta(CONFIG_THREAD *); static void *worker(void *); static uint64_t wtperf_rand(CONFIG_THREAD *); @@ -104,24 +106,93 @@ get_next_incr(CONFIG *cfg) return (__wt_atomic_add64(&cfg->insert_key, 1)); } +/* + * Each time this function is called we will overwrite the first and one + * other element in the value buffer. + */ static void randomize_value(CONFIG_THREAD *thread, char *value_buf) { uint8_t *vb; - uint32_t i; + uint32_t i, max_range, rand_val; + + /* + * Limit how much of the buffer we validate for length, this means + * that only threads that do growing updates will ever make changes to + * values outside of the initial value size, but that's a fair trade + * off for avoiding figuring out how long the value is more accurately + * in this performance sensitive function. + */ + if (thread->workload == NULL || thread->workload->update_delta == 0) + max_range = thread->cfg->value_sz; + else if (thread->workload->update_delta > 0) + max_range = thread->cfg->value_sz_max; + else + max_range = thread->cfg->value_sz_min; /* - * Each time we're called overwrite value_buf[0] and one other - * randomly chosen byte (other than the trailing NUL). - * Make sure we don't write a NUL: keep the value the same length. + * Generate a single random value and re-use it. We generally only + * have small ranges in this function, so avoiding a bunch of calls + * is worthwhile. + */ + rand_val = __wt_random(&thread->rnd); + i = rand_val % (max_range - 1); + + /* + * Ensure we don't write past the end of a value when configured for + * randomly sized values. */ - i = __wt_random(&thread->rnd) % (thread->cfg->value_sz - 1); while (value_buf[i] == '\0' && i > 0) --i; - if (i > 0) { - vb = (uint8_t *)value_buf; - vb[0] = (__wt_random(&thread->rnd) % 255) + 1; - vb[i] = (__wt_random(&thread->rnd) % 255) + 1; + + vb = (uint8_t *)value_buf; + vb[0] = ((rand_val >> 8) % 255) + 1; + /* + * If i happened to be 0, we'll be re-writing the same value + * twice, but that doesn't matter. + */ + vb[i] = ((rand_val >> 16) % 255) + 1; +} + +/* + * Figure out and extend the size of the value string, used for growing + * updates. We know that the value to be updated is in the threads value + * scratch buffer. + */ +static inline void +update_value_delta(CONFIG_THREAD *thread) +{ + CONFIG *cfg; + char * value; + int64_t delta, len, new_len; + + cfg = thread->cfg; + value = thread->value_buf; + delta = thread->workload->update_delta; + len = (int64_t)strlen(value); + + if (delta == INT64_MAX) + delta = __wt_random(&thread->rnd) % + (cfg->value_sz_max - cfg->value_sz); + + /* Ensure we aren't changing across boundaries */ + if (delta > 0 && len + delta > cfg->value_sz_max) + delta = cfg->value_sz_max - len; + else if (delta < 0 && len + delta < cfg->value_sz_min) + delta = cfg->value_sz_min - len; + + /* Bail if there isn't anything to do */ + if (delta == 0) + return; + + if (delta < 0) + value[len + delta] = '\0'; + else { + /* Extend the value by the configured amount. */ + for (new_len = len; + new_len < cfg->value_sz_max && new_len - len < delta; + new_len++) + value[new_len] = 'a'; } } @@ -623,8 +694,10 @@ worker(void *arg) * Copy as much of the previous value as is * safe, and be sure to NUL-terminate. */ - strncpy(value_buf, value, cfg->value_sz); - value_buf[cfg->value_sz - 1] = '\0'; + strncpy(value_buf, + value, cfg->value_sz_max - 1); + if (thread->workload->update_delta != 0) + update_value_delta(thread); if (value_buf[0] == 'a') value_buf[0] = 'b'; else @@ -1517,7 +1590,7 @@ close_reopen(CONFIG *cfg) { int ret; - if (!cfg->reopen_connection) + if (!cfg->readonly && !cfg->reopen_connection) return (0); /* * Reopen the connection. We do this so that the workload phase always @@ -1533,7 +1606,7 @@ close_reopen(CONFIG *cfg) return (ret); } if ((ret = wiredtiger_open( - cfg->home, NULL, cfg->conn_config, &cfg->conn)) != 0) { + cfg->home, NULL, cfg->reopen_config, &cfg->conn)) != 0) { lprintf(cfg, ret, 0, "Re-opening the connection failed"); return (ret); } @@ -1595,7 +1668,7 @@ execute_workload(CONFIG *cfg) for (threads = cfg->workers, i = 0, workp = cfg->workload; i < cfg->workload_cnt; ++i, ++workp) { lprintf(cfg, 0, 1, - "Starting workload #%d: %" PRId64 " threads, inserts=%" + "Starting workload #%u: %" PRId64 " threads, inserts=%" PRId64 ", reads=%" PRId64 ", updates=%" PRId64 ", truncate=%" PRId64 ", throttle=%" PRId64, i + 1, workp->threads, workp->insert, @@ -2194,7 +2267,7 @@ main(int argc, char *argv[]) * the compact operation, but not for the workloads. */ if (cfg->async_threads > 0) { - if (cfg->has_truncate > 0) { + if (F_ISSET(cfg, CFG_TRUNCATE)) { lprintf(cfg, 1, 0, "Cannot run truncate and async\n"); goto err; } @@ -2212,20 +2285,20 @@ main(int argc, char *argv[]) req_len = strlen(",async=(enabled=true,threads=)") + 4; cfg->async_config = dcalloc(req_len, 1); snprintf(cfg->async_config, req_len, - ",async=(enabled=true,threads=%d)", + ",async=(enabled=true,threads=%" PRIu32 ")", cfg->async_threads); } if ((ret = config_compress(cfg)) != 0) goto err; /* You can't have truncate on a random collection. */ - if (cfg->has_truncate && cfg->random_range) { + if (F_ISSET(cfg, CFG_TRUNCATE) && cfg->random_range) { lprintf(cfg, 1, 0, "Cannot run truncate and random_range\n"); goto err; } /* We can't run truncate with more than one table. */ - if (cfg->has_truncate && cfg->table_count > 1) { + if (F_ISSET(cfg, CFG_TRUNCATE) && cfg->table_count > 1) { lprintf(cfg, 1, 0, "Cannot truncate more than 1 table\n"); goto err; } @@ -2297,9 +2370,25 @@ main(int argc, char *argv[]) req_len = strlen(cfg->table_config) + strlen(LOG_PARTIAL_CONFIG) + 1; cfg->partial_config = dcalloc(req_len, 1); - snprintf((char *)cfg->partial_config, req_len, "%s%s", - (char *)cfg->table_config, LOG_PARTIAL_CONFIG); + snprintf(cfg->partial_config, req_len, "%s%s", + cfg->table_config, LOG_PARTIAL_CONFIG); } + /* + * Set the config for reopen. If readonly add in that string. + * If not readonly then just copy the original conn_config. + */ + if (cfg->readonly) + req_len = strlen(cfg->conn_config) + + strlen(READONLY_CONFIG) + 1; + else + req_len = strlen(cfg->conn_config) + 1; + cfg->reopen_config = dcalloc(req_len, 1); + if (cfg->readonly) + snprintf(cfg->reopen_config, req_len, "%s%s", + cfg->conn_config, READONLY_CONFIG); + else + snprintf(cfg->reopen_config, req_len, "%s", + cfg->conn_config); /* Sanity-check the configuration. */ if ((ret = config_sanity(cfg)) != 0) @@ -2357,7 +2446,8 @@ start_threads(CONFIG *cfg, * strings: trailing NUL is included in the size. */ thread->key_buf = dcalloc(cfg->key_sz, 1); - thread->value_buf = dcalloc(cfg->value_sz, 1); + thread->value_buf = dcalloc(cfg->value_sz_max, 1); + /* * Initialize and then toss in a bit of random values if needed. */ |