summaryrefslogtreecommitdiff
path: root/bench/wtperf/wtperf.c
diff options
context:
space:
mode:
Diffstat (limited to 'bench/wtperf/wtperf.c')
-rw-r--r--bench/wtperf/wtperf.c134
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.
*/