331 lines
7.9 KiB
C
331 lines
7.9 KiB
C
/*-
|
|
* Public Domain 2014-2016 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"
|
|
|
|
/*
|
|
* Return total insert operations for the populate phase.
|
|
*/
|
|
uint64_t
|
|
sum_pop_ops(CONFIG *cfg)
|
|
{
|
|
CONFIG_THREAD *thread;
|
|
uint64_t total;
|
|
u_int i;
|
|
|
|
total = 0;
|
|
|
|
for (i = 0, thread = cfg->popthreads;
|
|
thread != NULL && i < cfg->populate_threads; ++i, ++thread)
|
|
total += thread->insert.ops;
|
|
return (total);
|
|
}
|
|
|
|
/*
|
|
* Return total checkpoint operations.
|
|
*/
|
|
uint64_t
|
|
sum_ckpt_ops(CONFIG *cfg)
|
|
{
|
|
CONFIG_THREAD *thread;
|
|
uint64_t total;
|
|
u_int i;
|
|
|
|
total = 0;
|
|
|
|
for (i = 0, thread = cfg->ckptthreads;
|
|
thread != NULL && i < cfg->checkpoint_threads; ++i, ++thread)
|
|
total += thread->ckpt.ops;
|
|
return (total);
|
|
}
|
|
|
|
/*
|
|
* Return total operations count for the worker threads.
|
|
*/
|
|
static uint64_t
|
|
sum_ops(CONFIG *cfg, size_t field_offset)
|
|
{
|
|
CONFIG_THREAD *thread;
|
|
uint64_t total;
|
|
int64_t i, th_cnt;
|
|
|
|
total = 0;
|
|
if (cfg->popthreads == NULL) {
|
|
thread = cfg->workers;
|
|
th_cnt = cfg->workers_cnt;
|
|
} else {
|
|
thread = cfg->popthreads;
|
|
th_cnt = cfg->populate_threads;
|
|
}
|
|
for (i = 0; thread != NULL && i < th_cnt; ++i, ++thread)
|
|
total += ((TRACK *)((uint8_t *)thread + field_offset))->ops;
|
|
|
|
return (total);
|
|
}
|
|
uint64_t
|
|
sum_insert_ops(CONFIG *cfg)
|
|
{
|
|
return (sum_ops(cfg, offsetof(CONFIG_THREAD, insert)));
|
|
}
|
|
uint64_t
|
|
sum_read_ops(CONFIG *cfg)
|
|
{
|
|
return (sum_ops(cfg, offsetof(CONFIG_THREAD, read)));
|
|
}
|
|
uint64_t
|
|
sum_truncate_ops(CONFIG *cfg)
|
|
{
|
|
return (sum_ops(cfg, offsetof(CONFIG_THREAD, truncate)));
|
|
}
|
|
uint64_t
|
|
sum_update_ops(CONFIG *cfg)
|
|
{
|
|
return (sum_ops(cfg, offsetof(CONFIG_THREAD, update)));
|
|
}
|
|
|
|
/*
|
|
* latency_op --
|
|
* Get average, minimum and maximum latency for this period for a
|
|
* particular operation.
|
|
*/
|
|
static void
|
|
latency_op(CONFIG *cfg,
|
|
size_t field_offset, uint32_t *avgp, uint32_t *minp, uint32_t *maxp)
|
|
{
|
|
CONFIG_THREAD *thread;
|
|
TRACK *track;
|
|
uint64_t ops, latency, tmp;
|
|
int64_t i, th_cnt;
|
|
uint32_t max, min;
|
|
|
|
ops = latency = 0;
|
|
max = 0;
|
|
min = UINT32_MAX;
|
|
|
|
if (cfg->popthreads == NULL) {
|
|
thread = cfg->workers;
|
|
th_cnt = cfg->workers_cnt;
|
|
} else {
|
|
thread = cfg->popthreads;
|
|
th_cnt = cfg->populate_threads;
|
|
}
|
|
for (i = 0; thread != NULL && i < th_cnt; ++i, ++thread) {
|
|
track = (TRACK *)((uint8_t *)thread + field_offset);
|
|
tmp = track->latency_ops;
|
|
ops += tmp - track->last_latency_ops;
|
|
track->last_latency_ops = tmp;
|
|
tmp = track->latency;
|
|
latency += tmp - track->last_latency;
|
|
track->last_latency = tmp;
|
|
|
|
if (min > track->min_latency)
|
|
min = track->min_latency;
|
|
track->min_latency = UINT32_MAX;
|
|
if (max < track->max_latency)
|
|
max = track->max_latency;
|
|
track->max_latency = 0;
|
|
}
|
|
|
|
if (ops == 0)
|
|
*avgp = *minp = *maxp = 0;
|
|
else {
|
|
*minp = min;
|
|
*maxp = max;
|
|
*avgp = (uint32_t)(latency / ops);
|
|
}
|
|
}
|
|
void
|
|
latency_read(CONFIG *cfg, uint32_t *avgp, uint32_t *minp, uint32_t *maxp)
|
|
{
|
|
static uint32_t last_avg = 0, last_max = 0, last_min = 0;
|
|
|
|
latency_op(cfg, offsetof(CONFIG_THREAD, read), avgp, minp, maxp);
|
|
|
|
/*
|
|
* If nothing happened, graph the average, minimum and maximum as they
|
|
* were the last time, it keeps the graphs from having discontinuities.
|
|
*/
|
|
if (*minp == 0) {
|
|
*avgp = last_avg;
|
|
*minp = last_min;
|
|
*maxp = last_max;
|
|
} else {
|
|
last_avg = *avgp;
|
|
last_min = *minp;
|
|
last_max = *maxp;
|
|
}
|
|
}
|
|
void
|
|
latency_insert(CONFIG *cfg, uint32_t *avgp, uint32_t *minp, uint32_t *maxp)
|
|
{
|
|
static uint32_t last_avg = 0, last_max = 0, last_min = 0;
|
|
|
|
latency_op(cfg, offsetof(CONFIG_THREAD, insert), avgp, minp, maxp);
|
|
|
|
/*
|
|
* If nothing happened, graph the average, minimum and maximum as they
|
|
* were the last time, it keeps the graphs from having discontinuities.
|
|
*/
|
|
if (*minp == 0) {
|
|
*avgp = last_avg;
|
|
*minp = last_min;
|
|
*maxp = last_max;
|
|
} else {
|
|
last_avg = *avgp;
|
|
last_min = *minp;
|
|
last_max = *maxp;
|
|
}
|
|
}
|
|
void
|
|
latency_update(CONFIG *cfg, uint32_t *avgp, uint32_t *minp, uint32_t *maxp)
|
|
{
|
|
static uint32_t last_avg = 0, last_max = 0, last_min = 0;
|
|
|
|
latency_op(cfg, offsetof(CONFIG_THREAD, update), avgp, minp, maxp);
|
|
|
|
/*
|
|
* If nothing happened, graph the average, minimum and maximum as they
|
|
* were the last time, it keeps the graphs from having discontinuities.
|
|
*/
|
|
if (*minp == 0) {
|
|
*avgp = last_avg;
|
|
*minp = last_min;
|
|
*maxp = last_max;
|
|
} else {
|
|
last_avg = *avgp;
|
|
last_min = *minp;
|
|
last_max = *maxp;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* sum_latency --
|
|
* Sum latency for a set of threads.
|
|
*/
|
|
static void
|
|
sum_latency(CONFIG *cfg, size_t field_offset, TRACK *total)
|
|
{
|
|
CONFIG_THREAD *thread;
|
|
TRACK *trk;
|
|
int64_t i;
|
|
u_int j;
|
|
|
|
memset(total, 0, sizeof(*total));
|
|
|
|
for (i = 0, thread = cfg->workers;
|
|
thread != NULL && i < cfg->workers_cnt; ++i, ++thread) {
|
|
trk = (TRACK *)((uint8_t *)thread + field_offset);
|
|
|
|
for (j = 0; j < ELEMENTS(trk->us); ++j) {
|
|
total->ops += trk->us[j];
|
|
total->us[j] += trk->us[j];
|
|
}
|
|
for (j = 0; j < ELEMENTS(trk->ms); ++j) {
|
|
total->ops += trk->ms[j];
|
|
total->ms[j] += trk->ms[j];
|
|
}
|
|
for (j = 0; j < ELEMENTS(trk->sec); ++j) {
|
|
total->ops += trk->sec[j];
|
|
total->sec[j] += trk->sec[j];
|
|
}
|
|
}
|
|
}
|
|
static void
|
|
sum_insert_latency(CONFIG *cfg, TRACK *total)
|
|
{
|
|
sum_latency(cfg, offsetof(CONFIG_THREAD, insert), total);
|
|
}
|
|
static void
|
|
sum_read_latency(CONFIG *cfg, TRACK *total)
|
|
{
|
|
sum_latency(cfg, offsetof(CONFIG_THREAD, read), total);
|
|
}
|
|
static void
|
|
sum_update_latency(CONFIG *cfg, TRACK *total)
|
|
{
|
|
sum_latency(cfg, offsetof(CONFIG_THREAD, update), total);
|
|
}
|
|
|
|
static void
|
|
latency_print_single(CONFIG *cfg, TRACK *total, const char *name)
|
|
{
|
|
FILE *fp;
|
|
u_int i;
|
|
uint64_t cumops;
|
|
char path[1024];
|
|
|
|
snprintf(path, sizeof(path), "%s/latency.%s", cfg->monitor_dir, name);
|
|
if ((fp = fopen(path, "w")) == NULL) {
|
|
lprintf(cfg, errno, 0, "%s", path);
|
|
return;
|
|
}
|
|
|
|
fprintf(fp,
|
|
"#usecs,operations,cumulative-operations,total-operations\n");
|
|
cumops = 0;
|
|
for (i = 0; i < ELEMENTS(total->us); ++i) {
|
|
if (total->us[i] == 0)
|
|
continue;
|
|
cumops += total->us[i];
|
|
fprintf(fp,
|
|
"%u,%" PRIu32 ",%" PRIu64 ",%" PRIu64 "\n",
|
|
(i + 1), total->us[i], cumops, total->ops);
|
|
}
|
|
for (i = 1; i < ELEMENTS(total->ms); ++i) {
|
|
if (total->ms[i] == 0)
|
|
continue;
|
|
cumops += total->ms[i];
|
|
fprintf(fp,
|
|
"%llu,%" PRIu32 ",%" PRIu64 ",%" PRIu64 "\n",
|
|
ms_to_us(i + 1), total->ms[i], cumops, total->ops);
|
|
}
|
|
for (i = 1; i < ELEMENTS(total->sec); ++i) {
|
|
if (total->sec[i] == 0)
|
|
continue;
|
|
cumops += total->sec[i];
|
|
fprintf(fp,
|
|
"%llu,%" PRIu32 ",%" PRIu64 ",%" PRIu64 "\n",
|
|
sec_to_us(i + 1), total->sec[i], cumops, total->ops);
|
|
}
|
|
|
|
(void)fclose(fp);
|
|
}
|
|
|
|
void
|
|
latency_print(CONFIG *cfg)
|
|
{
|
|
TRACK total;
|
|
|
|
sum_insert_latency(cfg, &total);
|
|
latency_print_single(cfg, &total, "insert");
|
|
sum_read_latency(cfg, &total);
|
|
latency_print_single(cfg, &total, "read");
|
|
sum_update_latency(cfg, &total);
|
|
latency_print_single(cfg, &total, "update");
|
|
}
|