summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/bench/wtperf/wtperf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/wiredtiger/bench/wtperf/wtperf.c')
-rw-r--r--src/third_party/wiredtiger/bench/wtperf/wtperf.c341
1 files changed, 235 insertions, 106 deletions
diff --git a/src/third_party/wiredtiger/bench/wtperf/wtperf.c b/src/third_party/wiredtiger/bench/wtperf/wtperf.c
index 3c13304f1c1..f6c92a12ffe 100644
--- a/src/third_party/wiredtiger/bench/wtperf/wtperf.c
+++ b/src/third_party/wiredtiger/bench/wtperf/wtperf.c
@@ -39,7 +39,7 @@ static int execute_workload(WTPERF *);
static int find_table_count(WTPERF *);
static WT_THREAD_RET monitor(void *);
static WT_THREAD_RET populate_thread(void *);
-static void randomize_value(WTPERF_THREAD *, char *);
+static void randomize_value(WTPERF_THREAD *, char *, int64_t);
static void recreate_dir(const char *);
static WT_THREAD_RET scan_worker(void *);
static int start_all_runs(WTPERF *);
@@ -48,7 +48,7 @@ static void start_threads(
WTPERF *, WORKLOAD *, WTPERF_THREAD *, u_int, WT_THREAD_CALLBACK (*)(void *));
static void stop_threads(u_int, WTPERF_THREAD *);
static WT_THREAD_RET thread_run_wtperf(void *);
-static void update_value_delta(WTPERF_THREAD *);
+static void update_value_delta(WTPERF_THREAD *, int64_t);
static WT_THREAD_RET worker(void *);
static uint64_t wtperf_rand(WTPERF_THREAD *);
@@ -65,10 +65,11 @@ get_next_incr(WTPERF *wtperf)
/*
* Each time this function is called we will overwrite the first and one other element in the value
- * buffer.
+ * buffer. The delta can be zero for insert operations and may have a value for update or modify
+ * workloads.
*/
static void
-randomize_value(WTPERF_THREAD *thread, char *value_buf)
+randomize_value(WTPERF_THREAD *thread, char *value_buf, int64_t delta)
{
CONFIG_OPTS *opts;
uint8_t *vb;
@@ -78,13 +79,13 @@ randomize_value(WTPERF_THREAD *thread, char *value_buf)
/*
* 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.
+ * growing updates/modifies 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)
+ if (delta == 0)
max_range = opts->value_sz;
- else if (thread->workload->update_delta > 0)
+ else if (delta > 0)
max_range = opts->value_sz_max;
else
max_range = opts->value_sz_min;
@@ -134,21 +135,20 @@ map_key_to_table(CONFIG_OPTS *opts, uint64_t k)
}
/*
- * 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.
+ * Figure out and extend the size of the value string, used for growing updates/modifies. Delta is
+ * the value to be updated according to the thread operation.
*/
static inline void
-update_value_delta(WTPERF_THREAD *thread)
+update_value_delta(WTPERF_THREAD *thread, int64_t delta)
{
CONFIG_OPTS *opts;
WTPERF *wtperf;
char *value;
- int64_t delta, len, new_len;
+ int64_t len, new_len;
wtperf = thread->wtperf;
opts = wtperf->opts;
value = thread->value_buf;
- delta = thread->workload->update_delta;
len = (int64_t)strlen(value);
if (delta == INT64_MAX)
@@ -296,6 +296,8 @@ op_name(uint8_t *op)
return ("insert");
case WORKER_INSERT_RMW:
return ("insert_rmw");
+ case WORKER_MODIFY:
+ return ("modify");
case WORKER_READ:
return ("read");
case WORKER_TRUNCATE:
@@ -385,14 +387,15 @@ worker_async(void *arg)
goto op_err;
case WORKER_INSERT:
if (opts->random_value)
- randomize_value(thread, value_buf);
+ randomize_value(thread, value_buf, 0);
asyncop->set_value(asyncop, value_buf);
if ((ret = asyncop->insert(asyncop)) == 0)
break;
goto op_err;
case WORKER_UPDATE:
if (opts->random_value)
- randomize_value(thread, value_buf);
+ randomize_value(
+ thread, value_buf, thread->workload ? thread->workload->update_delta : 0);
asyncop->set_value(asyncop, value_buf);
if ((ret = asyncop->update(asyncop)) == 0)
break;
@@ -504,14 +507,16 @@ worker(void *arg)
WTPERF_THREAD *thread;
WT_CONNECTION *conn;
WT_CURSOR **cursors, *cursor, *log_table_cursor, *tmp_cursor;
+ WT_ITEM newv, oldv;
+ WT_MODIFY entries[MAX_MODIFY_NUM];
WT_SESSION *session;
- size_t i;
- uint32_t total_table_count;
- int64_t ops, ops_per_txn;
+ size_t i, iter, modify_offset, modify_size, total_modify_size, value_len;
+ int64_t delta, ops, ops_per_txn;
uint64_t log_id, next_val, usecs;
+ uint32_t rand_val, total_table_count;
uint8_t *op, *op_end;
- int measure_latency, ret, truncated;
- char *value_buf, *key_buf, *value;
+ int measure_latency, nmodify, ret, truncated;
+ char *key_buf, *value, *value_buf;
char buf[512];
thread = (WTPERF_THREAD *)arg;
@@ -607,12 +612,17 @@ worker(void *arg)
else
next_val = opts->icount + get_next_incr(wtperf);
break;
+ case WORKER_MODIFY:
+ trk = &thread->modify;
+ /* FALLTHROUGH */
case WORKER_READ:
- trk = &thread->read;
+ if (*op == WORKER_READ)
+ trk = &thread->read;
/* FALLTHROUGH */
case WORKER_UPDATE:
if (*op == WORKER_UPDATE)
trk = &thread->update;
+
next_val = wtperf_rand(thread);
/*
@@ -681,7 +691,7 @@ worker(void *arg)
/* FALLTHROUGH */
case WORKER_INSERT:
if (opts->random_value)
- randomize_value(thread, value_buf);
+ randomize_value(thread, value_buf, 0);
cursor->set_value(cursor, value_buf);
if ((ret = cursor->insert(cursor)) == 0)
break;
@@ -697,6 +707,7 @@ worker(void *arg)
break;
}
goto op_err;
+ case WORKER_MODIFY:
case WORKER_UPDATE:
if ((ret = cursor->search(cursor)) == 0) {
if ((ret = cursor->get_value(cursor, &value)) != 0) {
@@ -707,24 +718,104 @@ worker(void *arg)
* Copy as much of the previous value as is safe, and be sure to NUL-terminate.
*/
strncpy(value_buf, value, opts->value_sz_max - 1);
- if (workload->update_delta != 0)
- update_value_delta(thread);
+
+ if (*op == WORKER_MODIFY)
+ delta = workload->modify_delta;
+ else
+ delta = workload->update_delta;
+
+ if (delta != 0)
+ update_value_delta(thread, delta);
if (value_buf[0] == 'a')
value_buf[0] = 'b';
else
value_buf[0] = 'a';
if (opts->random_value)
- randomize_value(thread, value_buf);
- cursor->set_value(cursor, value_buf);
- if ((ret = cursor->update(cursor)) == 0)
- break;
+ randomize_value(thread, value_buf, delta);
+
+ if (*op == WORKER_UPDATE) {
+ cursor->set_value(cursor, value_buf);
+ if ((ret = cursor->update(cursor)) == 0)
+ break;
+ goto op_err;
+ }
+
+ /*
+ * Distribute the modifications across the whole document. We randomly choose up to
+ * the maximum number of modifications and modify up to the maximum percent of the
+ * record size.
+ */
+ nmodify = MAX_MODIFY_NUM;
+
+ /*
+ * The maximum that will be modified is a fixed percentage of the total record size.
+ */
+ value_len = strlen(value);
+ total_modify_size = value_len / MAX_MODIFY_PCT;
+
+ /*
+ * Randomize the maximum modification size and offset per modify.
+ */
+ rand_val = __wt_random(&thread->rnd);
+ if ((total_modify_size / (size_t)nmodify) != 0)
+ modify_size = rand_val % (total_modify_size / (size_t)nmodify);
+ else
+ modify_size = 0;
+
+ /*
+ * Offset location difference between modifications
+ */
+ if ((value_len / (size_t)nmodify) != 0)
+ modify_offset = (size_t)rand_val % (value_len / (size_t)nmodify);
+ else
+ modify_offset = 0;
+
+ /*
+ * Make sure the offset is more than size, otherwise modifications don't spread
+ * properly.
+ */
+ if (modify_offset < modify_size)
+ modify_offset = modify_size + 1;
+
+ for (iter = (size_t)nmodify; iter > 0; iter--)
+ memmove(&value_buf[(iter * modify_offset) - modify_offset],
+ &value_buf[(iter * modify_offset) - modify_size], modify_size);
+
+ /*
+ * Increase the number of modifications, so that normal modify operations succeeded.
+ */
+ if (!workload->modify_force_update)
+ nmodify++;
+
+ oldv.data = value;
+ oldv.size = value_len;
+
+ newv.data = value_buf;
+ newv.size = strlen(value_buf);
+
+ /*
+ * Pass the old and new data to find out the modify vectors, according to the passed
+ * input. This function may fail when the modifications count reaches the maximum
+ * number of modifications that are allowed for the modify operation.
+ */
+ ret = wiredtiger_calc_modify(
+ session, &oldv, &newv, total_modify_size, entries, &nmodify);
+
+ if (ret == WT_NOTFOUND || workload->modify_force_update) {
+ cursor->set_value(cursor, value_buf);
+ if ((ret = cursor->update(cursor)) == 0)
+ break;
+ } else {
+ if ((ret = cursor->modify(cursor, entries, nmodify)) == 0)
+ break;
+ }
goto op_err;
}
/*
* Reads can fail with WT_NOTFOUND: we may be searching in a random range, or an insert
* thread might have updated the last record in the table but not yet finished the
- * actual insert. Count failed search in a random range as a "read".
+ * actual insert. Count a failed search in a random range as a "read".
*/
if (ret == WT_NOTFOUND)
break;
@@ -896,7 +987,7 @@ run_mix_schedule(WTPERF *wtperf, WORKLOAD *workp)
opts = wtperf->opts;
if (workp->truncate != 0) {
- if (workp->insert != 0 || workp->read != 0 || workp->update != 0) {
+ if (workp->insert != 0 || workp->modify != 0 || workp->read != 0 || workp->update != 0) {
lprintf(wtperf, EINVAL, 0, "Can't configure truncate in a mixed workload");
return (EINVAL);
}
@@ -904,23 +995,27 @@ run_mix_schedule(WTPERF *wtperf, WORKLOAD *workp)
return (0);
}
- /* Confirm reads, inserts and updates cannot all be zero. */
- if (workp->insert == 0 && workp->read == 0 && workp->update == 0) {
+ /* Confirm inserts, modifies, reads and updates cannot all be zero. */
+ if (workp->insert == 0 && workp->modify == 0 && workp->read == 0 && workp->update == 0) {
lprintf(wtperf, EINVAL, 0, "no operations scheduled");
return (EINVAL);
}
/*
- * Check for a simple case where the thread is only doing insert or update operations (because
- * the default operation for a job-mix is read, the subsequent code works fine if only reads are
- * specified).
+ * Check for a simple case where the thread is only doing insert or modify or update operations
+ * (because the default operation for a job-mix is read, the subsequent code works fine if only
+ * reads are specified).
*/
- if (workp->insert != 0 && workp->read == 0 && workp->update == 0) {
+ if (workp->insert != 0 && workp->modify == 0 && workp->read == 0 && workp->update == 0) {
memset(
workp->ops, opts->insert_rmw ? WORKER_INSERT_RMW : WORKER_INSERT, sizeof(workp->ops));
return (0);
}
- if (workp->insert == 0 && workp->read == 0 && workp->update != 0) {
+ if (workp->insert == 0 && workp->modify != 0 && workp->read == 0 && workp->update == 0) {
+ memset(workp->ops, WORKER_MODIFY, sizeof(workp->ops));
+ return (0);
+ }
+ if (workp->insert == 0 && workp->modify == 0 && workp->read == 0 && workp->update != 0) {
memset(workp->ops, WORKER_UPDATE, sizeof(workp->ops));
return (0);
}
@@ -944,10 +1039,13 @@ run_mix_schedule(WTPERF *wtperf, WORKLOAD *workp)
*/
memset(workp->ops, WORKER_READ, sizeof(workp->ops));
- pct = (workp->insert * 100) / (workp->insert + workp->read + workp->update);
+ pct = (workp->insert * 100) / (workp->insert + workp->modify + workp->read + workp->update);
if (pct != 0)
run_mix_schedule_op(workp, opts->insert_rmw ? WORKER_INSERT_RMW : WORKER_INSERT, pct);
- pct = (workp->update * 100) / (workp->insert + workp->read + workp->update);
+ pct = (workp->modify * 100) / (workp->insert + workp->modify + workp->read + workp->update);
+ if (pct != 0)
+ run_mix_schedule_op(workp, WORKER_MODIFY, pct);
+ pct = (workp->update * 100) / (workp->insert + workp->modify + workp->read + workp->update);
if (pct != 0)
run_mix_schedule_op(workp, WORKER_UPDATE, pct);
return (0);
@@ -1025,7 +1123,7 @@ populate_thread(void *arg)
__wt_epoch(NULL, &start);
cursor->set_key(cursor, key_buf);
if (opts->random_value)
- randomize_value(thread, value_buf);
+ randomize_value(thread, value_buf, 0);
cursor->set_value(cursor, value_buf);
if ((ret = cursor->insert(cursor)) == WT_ROLLBACK) {
lprintf(wtperf, ret, 0, "insert retrying");
@@ -1149,7 +1247,7 @@ populate_async(void *arg)
generate_key(opts, key_buf, op);
asyncop->set_key(asyncop, key_buf);
if (opts->random_value)
- randomize_value(thread, value_buf);
+ randomize_value(thread, value_buf, 0);
asyncop->set_value(asyncop, value_buf);
if ((ret = asyncop->insert(asyncop)) != 0) {
lprintf(wtperf, ret, 0, "Failed inserting");
@@ -1195,13 +1293,15 @@ monitor(void *arg)
FILE *fp, *jfp;
WTPERF *wtperf;
size_t len;
- uint64_t min_thr, reads, inserts, updates;
- uint64_t cur_reads, cur_inserts, cur_updates;
- uint64_t last_reads, last_inserts, last_updates;
- uint32_t read_avg, read_min, read_max;
- uint32_t insert_avg, insert_min, insert_max;
- uint32_t update_avg, update_min, update_max;
+ uint64_t min_thr;
+ uint64_t inserts, modifies, reads, updates;
+ uint64_t cur_inserts, cur_modifies, cur_reads, cur_updates;
+ uint64_t last_inserts, last_modifies, last_reads, last_updates;
uint32_t latency_max, level;
+ uint32_t insert_avg, insert_max, insert_min;
+ uint32_t modify_avg, modify_max, modify_min;
+ uint32_t read_avg, read_max, read_min;
+ uint32_t update_avg, update_max, update_min;
u_int i;
size_t buf_size;
int msg_err;
@@ -1239,22 +1339,26 @@ monitor(void *arg)
fprintf(fp,
"#time,"
"totalsec,"
- "read ops per second,"
"insert ops per second,"
+ "modify ops per second,"
+ "read ops per second,"
"update ops per second,"
"checkpoints,"
"scans,"
- "read average latency(uS),"
- "read minimum latency(uS),"
- "read maximum latency(uS),"
"insert average latency(uS),"
"insert min latency(uS),"
"insert maximum latency(uS),"
+ "modify average latency(uS),"
+ "modify min latency(uS),"
+ "modify maximum latency(uS)"
+ "read average latency(uS),"
+ "read minimum latency(uS),"
+ "read maximum latency(uS),"
"update average latency(uS),"
"update min latency(uS),"
"update maximum latency(uS)"
"\n");
- last_reads = last_inserts = last_updates = 0;
+ last_inserts = last_modifies = last_reads = last_updates = 0;
while (!wtperf->stop) {
for (i = 0; i < opts->sample_interval; i++) {
sleep(1);
@@ -1271,15 +1375,15 @@ monitor(void *arg)
testutil_check(__wt_localtime(NULL, &t.tv_sec, &localt));
testutil_assert(strftime(buf, sizeof(buf), "%b %d %H:%M:%S", &localt) != 0);
- reads = sum_read_ops(wtperf);
inserts = sum_insert_ops(wtperf);
+ modifies = sum_modify_ops(wtperf);
+ reads = sum_read_ops(wtperf);
updates = sum_update_ops(wtperf);
- latency_read(wtperf, &read_avg, &read_min, &read_max);
latency_insert(wtperf, &insert_avg, &insert_min, &insert_max);
+ latency_modify(wtperf, &modify_avg, &modify_min, &modify_max);
+ latency_read(wtperf, &read_avg, &read_min, &read_max);
latency_update(wtperf, &update_avg, &update_min, &update_max);
- cur_reads = (reads - last_reads) / opts->sample_interval;
- cur_updates = (updates - last_updates) / opts->sample_interval;
/*
* For now the only item we need to worry about changing is inserts when we transition from
* the populate phase to workload phase.
@@ -1289,13 +1393,19 @@ monitor(void *arg)
else
cur_inserts = (inserts - last_inserts) / opts->sample_interval;
- (void)fprintf(fp, "%s,%" PRIu32 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64
- ",%c,%c"
- ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32
- ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 "\n",
- buf, wtperf->totalsec, cur_reads, cur_inserts, cur_updates, wtperf->ckpt ? 'Y' : 'N',
- wtperf->scan ? 'Y' : 'N', read_avg, read_min, read_max, insert_avg, insert_min,
- insert_max, update_avg, update_min, update_max);
+ cur_modifies = (modifies - last_modifies) / opts->sample_interval;
+ cur_reads = (reads - last_reads) / opts->sample_interval;
+ cur_updates = (updates - last_updates) / opts->sample_interval;
+
+ (void)fprintf(fp,
+ "%s,%" PRIu32 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64
+ ",%c,%c"
+ ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32
+ ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 "\n",
+ buf, wtperf->totalsec, cur_inserts, cur_modifies, cur_reads, cur_updates,
+ wtperf->ckpt ? 'Y' : 'N', wtperf->scan ? 'Y' : 'N', insert_avg, insert_min, insert_max,
+ modify_avg, modify_min, modify_max, read_avg, read_min, read_max, update_avg, update_min,
+ update_max);
if (jfp != NULL) {
buf_size = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &localt);
testutil_assert(buf_size != 0);
@@ -1307,23 +1417,27 @@ monitor(void *arg)
first = false;
}
(void)fprintf(jfp, "\"localTime\":\"%s\",\"wtperf\":{", buf);
- /* Note does not have initial comma before "read" */
- (void)fprintf(jfp, "\"read\":{\"ops per sec\":%" PRIu64 ",\"average latency\":%" PRIu32
- ",\"min latency\":%" PRIu32 ",\"max latency\":%" PRIu32 "}",
- cur_reads, read_avg, read_min, read_max);
+ /* Note does not have initial comma before "insert" */
(void)fprintf(jfp,
- ",\"insert\":{\"ops per sec\":%" PRIu64 ",\"average latency\":%" PRIu32
+ "\"insert\":{\"ops per sec\":%" PRIu64 ",\"average latency\":%" PRIu32
",\"min latency\":%" PRIu32 ",\"max latency\":%" PRIu32 "}",
cur_inserts, insert_avg, insert_min, insert_max);
(void)fprintf(jfp,
+ ",\"modify\":{\"ops per sec\":%" PRIu64 ",\"average latency\":%" PRIu32
+ ",\"min latency\":%" PRIu32 ",\"max latency\":%" PRIu32 "}",
+ cur_modifies, modify_avg, modify_min, modify_max);
+ (void)fprintf(jfp, ",\"read\":{\"ops per sec\":%" PRIu64 ",\"average latency\":%" PRIu32
+ ",\"min latency\":%" PRIu32 ",\"max latency\":%" PRIu32 "}",
+ cur_reads, read_avg, read_min, read_max);
+ (void)fprintf(jfp,
",\"update\":{\"ops per sec\":%" PRIu64 ",\"average latency\":%" PRIu32
",\"min latency\":%" PRIu32 ",\"max latency\":%" PRIu32 "}",
cur_updates, update_avg, update_min, update_max);
fprintf(jfp, "}}\n");
}
- if (latency_max != 0 &&
- (read_max > latency_max || insert_max > latency_max || update_max > latency_max)) {
+ if (latency_max != 0 && (insert_max > latency_max || modify_max > latency_max ||
+ read_max > latency_max || update_max > latency_max)) {
if (opts->max_latency_fatal) {
level = 1;
msg_err = WT_PANIC;
@@ -1334,13 +1448,14 @@ monitor(void *arg)
str = "WARNING";
}
lprintf(wtperf, msg_err, level,
- "%s: max latency exceeded: threshold %" PRIu32 " read max %" PRIu32
- " insert max %" PRIu32 " update max %" PRIu32,
- str, latency_max, read_max, insert_max, update_max);
+ "%s: max latency exceeded: threshold %" PRIu32 " insert max %" PRIu32
+ " modify max %" PRIu32 " read max %" PRIu32 " update max %" PRIu32,
+ str, latency_max, insert_max, modify_max, read_max, update_max);
}
- if (min_thr != 0 &&
- ((cur_reads != 0 && cur_reads < min_thr) || (cur_inserts != 0 && cur_inserts < min_thr) ||
- (cur_updates != 0 && cur_updates < min_thr))) {
+ if (min_thr != 0 && ((cur_inserts != 0 && cur_inserts < min_thr) ||
+ (cur_modifies != 0 && cur_modifies < min_thr) ||
+ (cur_reads != 0 && cur_reads < min_thr) ||
+ (cur_updates != 0 && cur_updates < min_thr))) {
if (opts->min_throughput_fatal) {
level = 1;
msg_err = WT_PANIC;
@@ -1351,12 +1466,13 @@ monitor(void *arg)
str = "WARNING";
}
lprintf(wtperf, msg_err, level,
- "%s: minimum throughput not met: threshold %" PRIu64 " reads %" PRIu64
- " inserts %" PRIu64 " updates %" PRIu64,
- str, min_thr, cur_reads, cur_inserts, cur_updates);
+ "%s: minimum throughput not met: threshold %" PRIu64 " inserts %" PRIu64
+ " modifies %" PRIu64 " reads %" PRIu64 " updates %" PRIu64,
+ str, min_thr, cur_inserts, cur_modifies, cur_reads, cur_updates);
}
- last_reads = reads;
last_inserts = inserts;
+ last_modifies = modifies;
+ last_reads = reads;
last_updates = updates;
}
@@ -1742,7 +1858,8 @@ execute_workload(WTPERF *wtperf)
WT_THREAD_CALLBACK (*pfunc)(void *);
wt_thread_t idle_table_cycle_thread;
uint64_t last_ckpts, last_scans;
- uint64_t last_inserts, last_reads, last_truncates, last_updates;
+ uint64_t last_inserts, last_reads, last_truncates;
+ uint64_t last_modifies, last_updates;
uint32_t interval, run_ops, run_time;
u_int i;
int ret;
@@ -1751,10 +1868,11 @@ execute_workload(WTPERF *wtperf)
wtperf->insert_key = 0;
wtperf->insert_ops = wtperf->read_ops = wtperf->truncate_ops = 0;
- wtperf->update_ops = 0;
+ wtperf->modify_ops = wtperf->update_ops = 0;
last_ckpts = last_scans = 0;
- last_inserts = last_reads = last_truncates = last_updates = 0;
+ last_inserts = last_reads = last_truncates = 0;
+ last_modifies = last_updates = 0;
ret = 0;
sessions = NULL;
@@ -1787,10 +1905,10 @@ execute_workload(WTPERF *wtperf)
for (threads = wtperf->workers, i = 0, workp = wtperf->workload; i < wtperf->workload_cnt;
++i, ++workp) {
lprintf(wtperf, 0, 1,
- "Starting workload #%u: %" PRId64 " threads, inserts=%" PRId64 ", reads=%" PRId64
- ", updates=%" PRId64 ", truncate=%" PRId64 ", throttle=%" PRIu64,
- i + 1, workp->threads, workp->insert, workp->read, workp->update, workp->truncate,
- workp->throttle);
+ "Starting workload #%u: %" PRId64 " threads, inserts=%" PRId64 ", modifies=%" PRId64
+ ", reads=%" PRId64 ", truncate=%" PRId64 ", updates=%" PRId64 ", throttle=%" PRIu64,
+ i + 1, workp->threads, workp->insert, workp->modify, workp->read, workp->truncate,
+ workp->update, workp->throttle);
/* Figure out the workload's schedule. */
if ((ret = run_mix_schedule(wtperf, workp)) != 0)
@@ -1825,12 +1943,15 @@ execute_workload(WTPERF *wtperf)
wtperf->ckpt_ops = sum_ckpt_ops(wtperf);
wtperf->scan_ops = sum_scan_ops(wtperf);
wtperf->insert_ops = sum_insert_ops(wtperf);
+ wtperf->modify_ops = sum_modify_ops(wtperf);
wtperf->read_ops = sum_read_ops(wtperf);
wtperf->update_ops = sum_update_ops(wtperf);
wtperf->truncate_ops = sum_truncate_ops(wtperf);
/* If we're checking total operations, see if we're done. */
- if (run_ops != 0 && run_ops <= wtperf->insert_ops + wtperf->read_ops + wtperf->update_ops)
+ if (run_ops != 0 &&
+ run_ops <=
+ wtperf->insert_ops + wtperf->modify_ops + wtperf->read_ops + wtperf->update_ops)
break;
/* If writing out throughput information, see if it's time. */
@@ -1839,17 +1960,19 @@ execute_workload(WTPERF *wtperf)
interval = opts->report_interval;
wtperf->totalsec += opts->report_interval;
- lprintf(wtperf, 0, 1, "%" PRIu64 " reads, %" PRIu64 " inserts, %" PRIu64
- " updates, %" PRIu64 " truncates, %" PRIu64 " checkpoints, %" PRIu64
- " scans in %" PRIu32 " secs (%" PRIu32 " total secs)",
- wtperf->read_ops - last_reads, wtperf->insert_ops - last_inserts,
- wtperf->update_ops - last_updates, wtperf->truncate_ops - last_truncates,
- wtperf->ckpt_ops - last_ckpts, wtperf->scan_ops - last_scans, opts->report_interval,
- wtperf->totalsec);
- last_reads = wtperf->read_ops;
+ lprintf(wtperf, 0, 1,
+ "%" PRIu64 " inserts, %" PRIu64 " modifies, %" PRIu64 " reads, %" PRIu64
+ " truncates, %" PRIu64 "updates, %" PRIu64 " checkpoints, %" PRIu64 " scans in %" PRIu32
+ " secs (%" PRIu32 " total secs)",
+ wtperf->insert_ops - last_inserts, wtperf->modify_ops - last_modifies,
+ wtperf->read_ops - last_reads, wtperf->truncate_ops - last_truncates,
+ wtperf->update_ops - last_updates, wtperf->ckpt_ops - last_ckpts,
+ wtperf->scan_ops - last_scans, opts->report_interval, wtperf->totalsec);
last_inserts = wtperf->insert_ops;
- last_updates = wtperf->update_ops;
+ last_modifies = wtperf->modify_ops;
+ last_reads = wtperf->read_ops;
last_truncates = wtperf->truncate_ops;
+ last_updates = wtperf->update_ops;
last_ckpts = wtperf->ckpt_ops;
last_scans = wtperf->scan_ops;
}
@@ -2304,23 +2427,28 @@ start_run(WTPERF *wtperf)
goto err;
/* One final summation of the operations we've completed. */
- wtperf->read_ops = sum_read_ops(wtperf);
wtperf->insert_ops = sum_insert_ops(wtperf);
+ wtperf->modify_ops = sum_modify_ops(wtperf);
+ wtperf->read_ops = sum_read_ops(wtperf);
wtperf->truncate_ops = sum_truncate_ops(wtperf);
wtperf->update_ops = sum_update_ops(wtperf);
wtperf->ckpt_ops = sum_ckpt_ops(wtperf);
wtperf->scan_ops = sum_scan_ops(wtperf);
- total_ops = wtperf->read_ops + wtperf->insert_ops + wtperf->update_ops;
+ total_ops = wtperf->insert_ops + wtperf->modify_ops + wtperf->read_ops + wtperf->update_ops;
run_time = opts->run_time == 0 ? 1 : opts->run_time;
lprintf(wtperf, 0, 1,
- "Executed %" PRIu64 " read operations (%" PRIu64 "%%) %" PRIu64 " ops/sec",
- wtperf->read_ops, (wtperf->read_ops * 100) / total_ops, wtperf->read_ops / run_time);
- lprintf(wtperf, 0, 1,
"Executed %" PRIu64 " insert operations (%" PRIu64 "%%) %" PRIu64 " ops/sec",
wtperf->insert_ops, (wtperf->insert_ops * 100) / total_ops,
wtperf->insert_ops / run_time);
lprintf(wtperf, 0, 1,
+ "Executed %" PRIu64 " modify operations (%" PRIu64 "%%) %" PRIu64 " ops/sec",
+ wtperf->modify_ops, (wtperf->modify_ops * 100) / total_ops,
+ wtperf->modify_ops / run_time);
+ lprintf(wtperf, 0, 1,
+ "Executed %" PRIu64 " read operations (%" PRIu64 "%%) %" PRIu64 " ops/sec",
+ wtperf->read_ops, (wtperf->read_ops * 100) / total_ops, wtperf->read_ops / run_time);
+ lprintf(wtperf, 0, 1,
"Executed %" PRIu64 " truncate operations (%" PRIu64 "%%) %" PRIu64 " ops/sec",
wtperf->truncate_ops, (wtperf->truncate_ops * 100) / total_ops,
wtperf->truncate_ops / run_time);
@@ -2706,16 +2834,17 @@ start_threads(WTPERF *wtperf, WORKLOAD *workp, WTPERF_THREAD *base, u_int num,
*/
memset(thread->value_buf, 'a', opts->value_sz - 1);
if (opts->random_value)
- randomize_value(thread, thread->value_buf);
+ randomize_value(thread, thread->value_buf, 0);
/*
* Every thread gets tracking information and is initialized for latency measurements, for
* the same reason.
*/
thread->ckpt.min_latency = thread->scan.min_latency = thread->insert.min_latency =
- thread->read.min_latency = thread->update.min_latency = UINT32_MAX;
+ thread->modify.min_latency = thread->read.min_latency = thread->update.min_latency =
+ UINT32_MAX;
thread->ckpt.max_latency = thread->scan.max_latency = thread->insert.max_latency =
- thread->read.max_latency = thread->update.max_latency = 0;
+ thread->modify.max_latency = thread->read.max_latency = thread->update.max_latency = 0;
}
/* Start the threads. */