Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Simplified the stats logic

  • Loading branch information...
commit 6f8254d7955c8c6f6784830714ce94faf7f180c9 1 parent b933153
@trondn trondn authored
Showing with 202 additions and 443 deletions.
  1. +27 −242 main.c
  2. +37 −31 memcachetest.h
  3. +131 −159 metrics.c
  4. +7 −11 metrics.h
View
269 main.c
@@ -47,6 +47,7 @@
#include "libmemc.h"
#include "metrics.h"
+#include "memcachetest.h"
#include "boxmuller.h"
#include "vbucket.h"
@@ -392,30 +393,6 @@ static void release_connection(struct connection *connection) {
}
/**
- * Convert a time (in ns) to a human readable form...
- * @param time the time in nanoseconds
- * @param buffer where to store the result
- * @param size the size of the buffer
- * @return buffer
- */
-static const char* hrtime2text(hrtime_t t, char *buffer, size_t size) {
- static const char * const extensions[] = {"ns", "us", "ms", "s" }; //TODO: get a greek Mu in here correctly
- int id = 0;
-
- while (t > 9999) {
- ++id;
- t /= 1000;
- if (id > 3) {
- break;
- }
- }
-
- snprintf(buffer, size, "%d %s", (int) t, extensions[id]);
- buffer[size - 1] = '\0';
- return buffer;
-}
-
-/**
* Convert a timeval structure to human readable form..
* @param val the value to convert
* @param buffer where to store the result
@@ -480,17 +457,16 @@ static int initialize_dataset(void) {
* @return 0 if success, -1 if an error occurs
*/
static int populate_dataset(struct thread_context *ctx) {
- struct report *rep = &ctx->thr_summary;
struct connection* connection = get_connection();
- int end = rep->offset + rep->total;
+ int end = ctx->offset + ctx->total;
char key[12];
size_t nkey;
- assert(end > rep->offset);
+ assert(end > ctx->offset);
if (verbose) {
- fprintf(stderr, "Populating from %d to %d\n", rep->offset, end);
+ fprintf(stderr, "Populating from %d to %d\n", ctx->offset, end);
}
- for (int ii = rep->offset; ii < end; ++ii) {
+ for (int ii = ctx->offset; ii < end; ++ii) {
nkey = snprintf(key, sizeof(key), "%d", ii);
if (memcached_set_wrapper(connection,
key,
@@ -545,16 +521,18 @@ static int populate_data(int no_threads) {
for (ii = 0; ii < no_threads; ++ii) {
struct thread_context *ctxi = &ctx[ii];
- ctxi->thr_summary.offset = offset;
- ctxi->thr_summary.total = perThread;
+ if (!initialize_thread_ctx(ctxi, offset,
+ (rest > 0) ? perThread + 1 : perThread)) {
+ abort();
+ }
offset += perThread;
if (rest > 0) {
--rest;
- ++ctxi->thr_summary.total;
++offset;
}
+
pthread_create(&threads[ii], 0, populate_thread_main,
- &ctx[ii]);
+ &ctx[ii]);
}
for (ii = 0; ii < no_threads; ++ii) {
@@ -567,7 +545,7 @@ static int populate_data(int no_threads) {
free(threads);
free(ctx);
} else { /* only one thread */
- struct thread_context ctx = {.thr_summary.offset=0, .thr_summary.total=no_items};
+ struct thread_context ctx = {.offset=0, .total=no_items};
if (populate_dataset(&ctx) == -1) {
return 1;
@@ -590,11 +568,9 @@ static int get_setval(void) {
static int test(struct thread_context *ctx) {
int ret = 0;
struct connection* connection;
- ctx->thr_summary.bestGet = ctx->thr_summary.worstGet = 99999999;
- ctx->thr_summary.worstGet = ctx->thr_summary.worstSet = 0;
char key[12];
size_t nkey;
- for (int ii = 0; ii < ctx->thr_summary.total; ++ii) {
+ for (int ii = 0; ii < ctx->total; ++ii) {
connection = get_connection();
int idx = get_setval();
nkey = snprintf(key, sizeof(key), "%d", idx);
@@ -605,15 +581,7 @@ static int test(struct thread_context *ctx) {
memcached_set_wrapper(connection, key, nkey,
datablock.data, dataset[idx]);
delta = gethrtime() - start;
- if (delta < ctx->thr_summary.bestSet) {
- ctx->thr_summary.bestSet = delta;
- }
- if (delta > ctx->thr_summary.worstSet) {
- ctx->thr_summary.worstSet = delta;
- }
- ctx->thr_summary.setDelta += delta;
- // record_tx(TX_SET, delta); Need to add sets!
- ++ctx->thr_summary.set;
+ record_tx(TX_SET, delta, ctx);
} else {
/* go set it from random data */
if (verbose) {
@@ -625,13 +593,6 @@ static int test(struct thread_context *ctx) {
void *data = memcached_get_wrapper(connection, key, nkey, &size);
delta = gethrtime() - start;
- if (delta < ctx->thr_summary.bestGet) {
- ctx->thr_summary.bestGet = delta;
- }
- if (delta > ctx->thr_summary.worstGet) {
- ctx->thr_summary.worstGet = delta;
- }
- ctx->thr_summary.getDelta += delta;
if (data != NULL) {
if (size != dataset[idx]) {
fprintf(stderr,
@@ -648,7 +609,6 @@ static int test(struct thread_context *ctx) {
fprintf(stderr, "missing data for <%s>\n", key);
// record_error(TX_GET, delta);
}
- ++ctx->thr_summary.get;
}
release_connection(connection);
}
@@ -943,215 +903,40 @@ int main(int argc, char **argv) {
do {
pthread_t *threads = calloc(sizeof (pthread_t), no_threads);
struct thread_context *ctx = calloc(sizeof (struct thread_context), no_threads);
- struct report *reports = calloc(sizeof (struct report), no_threads);
int ii;
- size_t set = 0;
- size_t get = 0;
- hrtime_t setDelta = 0;
- hrtime_t getDelta = 0;
- hrtime_t bestSet = MAXINT;
- hrtime_t bestGet = MAXINT;
- hrtime_t worstSet = 0;
- hrtime_t worstGet = 0;
- int bestGetTid = 0;
- int worstGetTid = 0;
- int bestSetTid = 0;
- int worstSetTid = 0;
-
-
- if (no_threads > 1 && no_iterations > 0) {
+
+ if (no_iterations > 0) {
int perThread = no_iterations / no_threads;
int rest = no_iterations % no_threads;
- int current = 0;
- int shift = 0;
for (ii = 0; ii < no_threads; ++ii) {
struct thread_context *ctxi = &ctx[ii];
- ctxi->thr_summary.total = perThread;
- ctxi->head = NULL;
+ if (!initialize_thread_ctx(ctxi, 0,
+ (rest > 0) ? perThread + 1 : perThread)) {
+ abort();
+ }
+
if (rest > 0) {
--rest;
- ++ctxi->thr_summary.total;
}
pthread_create(&threads[ii], 0, test_thread_main, &ctx[ii]);
}
-
- while (current < no_iterations) {
- struct report temp = { .offset = 0 };
- char buff[40];
- sleep(5);
- /* print average */
-
-
- for (ii = 0; ii < no_threads; ++ii) {
- struct thread_context *ctxi = &ctx[ii];
-
- temp.set += ctxi->thr_summary.set;
- temp.get += ctxi->thr_summary.get;
- temp.setDelta += ctxi->thr_summary.setDelta;
- temp.getDelta += ctxi->thr_summary.getDelta;
- }
-
- if (progress) {
- fprintf(stdout, "\rAvg: ");
- if (temp.set > 0) {
- fprintf(stdout, "set: %s (%ld) ",
- hrtime2text(temp.setDelta / temp.set,
- buff, sizeof (buff)), (long)temp.set);
- }
-
- if (temp.get > 0) {
- fprintf(stdout, "get: %s (%ld) ",
- hrtime2text(temp.getDelta / temp.get,
- buff, sizeof (buff)), (long)temp.get);
- }
- ++shift;
- if (shift % 10 == 0) {
- fprintf(stdout, "\n");
- }
- fflush(stdout);
- }
- current = temp.set + temp.get;
- }
-
-
- if (progress) {
- fprintf(stdout, ".\n");
- }
-
-
for (ii = 0; ii < no_threads; ++ii) {
void *ret;
pthread_join(threads[ii], &ret);
- struct thread_context *ctx = ret;
- struct report *rep = &ctx->thr_summary;
-
- set += rep->set;
- get += rep->get;
- setDelta += rep->setDelta;
- getDelta += rep->getDelta;
- if (rep->bestSet < bestSet) {
- bestSet = rep->bestSet;
- bestSetTid = ii;
- }
- if (rep->worstSet > worstSet) {
- worstSet = rep->worstSet;
- worstSetTid = ii;
- }
- if (rep->bestGet < bestGet) {
- bestGet = rep->bestGet;
- bestGetTid = ii;
- }
- if (rep->worstGet > worstGet) {
- worstGet = rep->worstGet;
- worstGetTid = ii;
- }
-
+ assert(ret == (void*)&ctx[ii]);
if (verbose) {
- char setTime[80];
- char getTime[80];
- char bestSetTime[80];
- char bestGetTime[80];
- char worstSetTime[80];
- char worstGetTime[80];
-
- printf("Thread: %d\n", ii);
- if (rep->set > 0) {
- printf(" Avg set: %s (%ld) min: %s max: %s\n",
- hrtime2text(rep->setDelta / rep->set,
- setTime, sizeof (setTime)),
- (long)rep->set,
- hrtime2text(rep->bestSet,
- bestSetTime, sizeof (bestSetTime)),
- hrtime2text(rep->worstSet,
- worstSetTime, sizeof (worstSetTime)));
-
- }
- if (rep->get > 0) {
- printf(" Avg get: %s (%ld) min: %s max: %s\n",
- hrtime2text(rep->getDelta / rep->get,
- getTime, sizeof (getTime)),
- (long)rep->get,
- hrtime2text(rep->bestGet,
- bestGetTime, sizeof (bestGetTime)),
- hrtime2text(rep->worstGet,
- worstGetTime, sizeof (worstGetTime)));
-
- }
+ fprintf(stdout, "Details from thread %d\n", ii);
+ print_metrics(&ctx[ii]);
}
- ctx = &ctx[ii];
}
- } else if (no_iterations > 0) {
- /* TODO: make this per context
- reports[0].total = no_iterations;
- test(&ctx[0]);
- set = reports[0].set;
- get = reports[0].get;
- setDelta = reports[0].setDelta;
- getDelta = reports[0].getDelta;
- bestSet = reports[0].bestSet;
- worstSet = reports[0].worstSet;
- bestGet = reports[0].bestGet;
- worstGet = reports[0].worstGet;
- */
-
- }
-
-
-/*
- struct ResultMetrics *getResults = calc_metrics(TX_GET); // this does only gets at the moment need a smarter calc_metrics
-*/
-
- /* print out the results */
-
-/*
- char tavg[80];
- char tmin[80];
- char tmax[80];
- char tmax90[80];
- char tmax95[80];
- printf("Get operations:\n");
- printf(" #of ops. min max avg max90th max95th\n");
- printf("%13ld", getResults->success_count);
- printf("%11.11s", hrtime2text(getResults->min_result, tmin, sizeof (tmin)));
- printf("%11.11s", hrtime2text(getResults->max_result, tmax, sizeof (tmax)));
- printf("%11.11s", hrtime2text(getResults->average, tavg, sizeof(tavg)));
- printf("%13.13s", hrtime2text(getResults->max90th_result, tmax90, sizeof(tmax90)));
- printf("%12.12s", hrtime2text(getResults->max95th_result, tmax95, sizeof(tmax95)));
-
- printf("\n\n");
- */
-
- nget += get;
- nset += set;
-
- printf("Average with %d threads:\n", no_threads);
- if (set > 0) {
- char avg[80];
- char best[80];
- char worst[80];
- hrtime2text(setDelta / ((set > 0) ? set : 1), avg, sizeof (avg));
- hrtime2text(bestSet, best, sizeof (best));
- hrtime2text(worstSet, worst, sizeof (worst));
-
- printf(" Avg set: %s (%ld) min: %s (%d) max: %s (%d)\n",
- avg, (long)set, best, bestSetTid, worst, worstSetTid);
- }
- if (get > 0) {
- char avg[80];
- char best[80];
- char worst[80];
- hrtime2text(getDelta / ((get > 0) ? get : 1), avg, sizeof (avg));
- hrtime2text(bestGet, best, sizeof (best));
- hrtime2text(worstGet, worst, sizeof (worst));
-
- printf(" Avg get: %s (%ld) min: %s (%d) max: %s (%d)\n",
- avg, (long)get, best, bestGetTid, worst, worstGetTid);
}
- free(reports);
+ fprintf(stdout, "Average with %d threads\n", no_threads);
+ print_aggregated_metrics(ctx, no_threads);
free(threads);
+ free(ctx);
} while (loop);
if (getrusage(RUSAGE_SELF, &rusage) == -1) {
View
68 memcachetest.h
@@ -1,55 +1,61 @@
-/*
+/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * See LICENSE.txt included in this distribution for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at LICENSE.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
* File: memcachetest.h
* Author: ingenthr
*
* Created on March 19, 2010, 3:01 PM
*/
+/*
+ * Portions Copyright 2010 Trond Norbye
+ * Simplified the logic to fit our needs.
+ */
-#ifndef _MEMCACHETEST_H
-#define _MEMCACHETEST_H
+#ifndef MEMCACHETEST_H
+#define MEMCACHETEST_H
+#include <stdbool.h>
#include "metrics.h"
#ifdef __cplusplus
extern "C" {
#endif
- /**
- * A struct holding the information I would like to measure for each test-run
- */
- struct report {
- /** The index in the items array to start at */
- int offset;
- /** The number of operations to execute */
- size_t total;
- /** The number of set-operation executed */
- size_t set;
- /** The total time of all of the set-operations */
- hrtime_t setDelta;
- /** The number of get-operations executed */
- size_t get;
- /** The total time of all of the get-operations */
- hrtime_t getDelta;
- /** The best set operation */
- hrtime_t bestSet;
- /** The best get operation */
- hrtime_t bestGet;
- /** The worst set operation */
- hrtime_t worstSet;
- /** The worst get operation */
- hrtime_t worstGet;
+ struct samples {
+ int current;
+ hrtime_t *set;
};
/**
* A struct for the info on the thread
*/
struct thread_context {
- struct TxnResult* head;
- struct report thr_summary;
+ int offset;
+ size_t total;
+ struct samples tx[TX_CAS - TX_GET];
+ /* struct report thr_summary; */
};
-
-
+ bool initialize_thread_ctx(struct thread_context *ctx,
+ int offset,
+ size_t total);
#ifdef __cplusplus
}
View
290 metrics.c
@@ -21,15 +21,9 @@
/*
* Portions Copyright 2009-2010 Matt Ingenthron
*/
-
/*
- * The metrics file is all about collecting metrics during a run and then
- * calculating key metrics after the run is complete.
- *
- * loosely reimplemented in C from Faban http://faban.sunsource.net
- *
- * @author Matt Ingenthron <ingenthr@cep.net>
- *
+ * Portions Copyright 2010 Trond Norbye
+ * Simplified the logic to fit our needs.
*/
#include "config.h"
@@ -38,191 +32,169 @@
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
+#include <stdbool.h>
#include "metrics.h"
#include "memcachetest.h"
-/* Stats for all transaction types - the first dimension of the array
- * is always the operation id. This is the index into the operations
- * array of the mix. The second dimension, existent only for histograms
- * is the bucket.
- */
-
-pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+bool initialize_thread_ctx(struct thread_context *ctx, int offset, size_t total)
+{
+ ctx->offset = offset;
+ ctx->total = total;
-const int RAMP_UP = 30;
-static struct TxnResult * txn_list_first = NULL;
+ for (int ii = 0; ii < TX_CAS - TX_GET; ++ii) {
+ ctx->tx[ii].set = calloc(ctx->total, sizeof(hrtime_t));
+ if (ctx->tx[ii].set == NULL) {
+ for (int jj = 0; jj < ii; ++jj) {
+ free(ctx->tx[jj].set);
+ }
+ return false;
+ }
+ }
+ return true;
+}
/**
- * Number of successful transactions during steady state.
- * This is used for final reporting and in-flight reporting of averages.
+ * A comparison-function used by qsort.
+ * @param p1 element 1 to compare
+ * @param p2 element 2 to compare
+ * @return -1, 0 or 1
*/
-int txCntStdy[6];
-
+static int compare(const void *p1, const void *p2)
+{
+ hrtime_t a = *((hrtime_t *)p1);
+ hrtime_t b = *((hrtime_t *)p2);
+
+ if (a < b) {
+ return -1;
+ } else if (a > b) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
/**
- * Number of failed transactions during steady state.
- * This is used for final reporting and in-flight reporting of averages.
+ * External interface
*/
-int errCntStdy[6];
-
-struct TxnRunStatus {
- int txnCount;
- int avgRespTime;
-};
-
-
-static void insert(struct thread_context *ctx, struct TxnResult* item) {
- if (ctx->head == NULL) {
- ctx->head = item;
- } else {
- struct TxnResult* ptr = ctx->head;
- int searching = 1;
-
- while (searching) {
- if (item->respTime <= ptr->respTime) {
- /* should be on the left */
- if (ptr->left == NULL) {
- ptr->left = item;
- searching = 0;
- } else {
- ptr = ptr->left;
- }
- } else {
- /* should be on the right */
- if (ptr->right == NULL) {
- ptr->right = item;
- searching = 0;
- } else {
- ptr = ptr->right;
- }
- }
- }
- }
+void record_tx(enum TxnType tx_type, hrtime_t time, struct thread_context *ctx) {
+ assert(tx_type >= 0 && tx_type < (TX_CAS - TX_GET));
+ ctx->tx[tx_type].set[ctx->tx[tx_type].current++] = time;
}
-static int walk(struct TxnResult* node, int (*walk_function)(void *, struct TxnResult* node), void *cookie) {
- int ret;
- if (node->left) {
- if ((ret = walk(node->left, walk_function, cookie)) != 0) {
- return ret;
- }
+struct ResultMetrics *calc_metrics(enum TxnType tx_type,
+ struct thread_context *ctx)
+{
+ struct ResultMetrics *ret = calloc(1, sizeof(*ret));
+ if (ret == NULL) {
+ return NULL;
}
- if ((ret = (*walk_function)(cookie, node) != 0)) {
+ struct samples *sample = &ctx->tx[tx_type];
+ if (sample->current == 0) {
return ret;
}
- if (node->right) {
- if ((ret = walk(node->right, walk_function, cookie)) != 0) {
- return ret;
- }
- }
+ // sort the result
+ qsort(sample->set, sample->current, sizeof(hrtime_t), compare);
- return 0;
-}
+ ret->success_count = sample->current ;
+ long percentile90 = (0.9) * (float) (ret->success_count - 1) + 1.0;
+ long percentile95 = (0.95) * (float) (ret->success_count - 1) + 1.0;
+
+ ret->max90th_result = sample->set[percentile90];
+ ret->max95th_result = sample->set[percentile95];
+ ret->min_result = sample->set[0];
+ ret->max_result = sample->set[sample->current - 1];
-#if 0
-static struct TxnResult *create_txn(struct TxnResult *item) {
- static struct TxnResult *items;
- static int no_left = 0;
- struct TxnResult *ret;
-
- if (no_left == 0) {
- // Need to allocate more items!!
- items = calloc(1000, sizeof (struct TxnResult));
- assert(items != NULL);
- no_left = 1000;
+ hrtime_t total = 0;
+ for (int ii = 0; ii < sample->current; ++ii) {
+ total += sample->set[ii];
}
- ret = items;
- ++items;
- --no_left;
- ret->respTime = item->respTime;
- ret->left = ret->right = NULL;
+ ret->average = total / sample->current;
return ret;
}
-#endif
-
-struct walker_execution_time {
- long current;
- long elementnum;
- hrtime_t exec_time;
-};
-
-static int get_exec_time_walker(void *cookie, struct TxnResult* node) {
- struct walker_execution_time *tim = cookie;
- if (tim->current < tim->elementnum) {
- tim->exec_time = node->respTime;
- ++tim->current;
- return 0;
- } else {
- return 1;
- }
-}
-/*
- * Get the execution time for a given element number in the list
- * @param elementnum the element number you want the execution time for
+/**
+ * Convert a time (in ns) to a human readable form...
+ * @param time the time in nanoseconds
+ * @param buffer where to store the result
+ * @param size the size of the buffer
+ * @return buffer
*/
-static hrtime_t get_exec_time(struct TxnResult* root, long elementnum) {
- struct walker_execution_time tim = { .current = 0, .exec_time = 0, .elementnum = elementnum };
-
- walk(root, get_exec_time_walker, &tim);
- return tim.exec_time;
-}
-
-struct walker_average {
- hrtime_t delta;
- long count;
-};
+static const char* hrtime2text(hrtime_t t, char *buffer, size_t size) {
+ static const char * const extensions[] = {"ns", "us", "ms", "s" }; //TODO: get a greek Mu in here correctly
+ int id = 0;
+
+ while (t > 9999) {
+ ++id;
+ t /= 1000;
+ if (id > 3) {
+ break;
+ }
+ }
-static int get_average_walker(void *cookie, struct TxnResult* node) {
- struct walker_average *a = cookie;
- ++a->count;
- a->delta += node->respTime;
- return 0;
+ snprintf(buffer, size, "%d %s", (int) t, extensions[id]);
+ buffer[size - 1] = '\0';
+ return buffer;
}
-/*
- * Get the execution time for a given element number in the list
- * @param elementnum the element number you want the execution time for
- */
-static hrtime_t calc_average(struct TxnResult* a) {
- struct walker_average avg = { .count = 0, .delta = 0 };
- walk(a, get_average_walker, &avg);
- return avg.delta / avg.count;
+static void print_details(enum TxnType tx_type, struct ResultMetrics *r) {
+ static const char * txt[] = { [TX_GET] = "Get",
+ [TX_SET] = "Set",
+ [TX_ADD] = "Add",
+ [TX_REPLACE] = "Replace",
+ [TX_APPEND] = "Append",
+ [TX_PREPEND] = "Prepend",
+ [TX_CAS] = "Cas" };
+
+
+ printf("%s operations:\n", txt[tx_type]);
+ char tavg[80];
+ char tmin[80];
+ char tmax[80];
+ char tmax90[80];
+ char tmax95[80];
+ printf(" #of ops. min max avg max90th max95th\n");
+ printf("%13ld%11.11s%11.11s%11.11s%13.13s%12.12s\n\n", r->success_count,
+ hrtime2text(r->min_result, tmin, sizeof (tmin)),
+ hrtime2text(r->max_result, tmax, sizeof (tmax)),
+ hrtime2text(r->average, tavg, sizeof(tavg)),
+ hrtime2text(r->max90th_result, tmax90, sizeof(tmax90)),
+ hrtime2text(r->max95th_result, tmax95, sizeof(tmax95)));
}
-/**
- * External interface
- */
-void record_tx(enum TxnType tx_type, hrtime_t time, struct thread_context *ctx) {
- struct TxnResult* new_txn = calloc(1, sizeof(struct TxnResult));
- new_txn->respTime = time;
- new_txn->left = new_txn->right = new_txn->next = NULL;
- insert(ctx, new_txn);
- txCntStdy[tx_type]++;
-}
-
-void record_error(enum TxnType tx_type, hrtime_t t) {
- (void)t;
- errCntStdy[tx_type]++;
+void print_metrics(struct thread_context *ctx) {
+ for (int ii = 0; ii < TX_CAS - TX_GET; ++ii) {
+ if (ctx->tx[ii].current > 0) {
+ struct ResultMetrics *r = calc_metrics(ii, ctx);
+ if (r) {
+ print_details(ii, r);
+ free(r);
+ }
+ }
+ }
}
-struct ResultMetrics *calc_metrics(enum TxnType tx_type) {
- struct ResultMetrics * ret = calloc(1, sizeof (struct ResultMetrics));
- ret->success_count = txCntStdy[tx_type];
+void print_aggregated_metrics(struct thread_context *ctx, int num)
+{
+ int total = 0;
+ for (int ii = 0; ii < num; ++ii) {
+ total += ctx[ii].total;
+ }
- long percentile90 = (0.9) * (float) (ret->success_count - 1) + 1.0;
- long percentile95 = (0.95) * (float) (ret->success_count - 1) + 1.0;
- assert(ret != NULL);
+ struct thread_context context;
+ memset(&context, 0, sizeof(context));
+ initialize_thread_ctx(&context, 0, total);
- ret->max90th_result = get_exec_time(txn_list_first, percentile90);
- ret->max95th_result = get_exec_time(txn_list_first, percentile95);
- ret->min_result = get_exec_time(txn_list_first, 0);
- ret->max_result = get_exec_time(txn_list_first, ret->success_count);
- ret->average = calc_average(txn_list_first);
+ for (int ii = 0; ii < num; ++ii) {
+ for (int jj = 0; jj < TX_CAS - TX_GET; ++jj) {
+ memcpy(context.tx[jj].set + context.tx[jj].current,
+ ctx[ii].tx[jj].set, ctx[ii].tx[jj].current * sizeof(hrtime_t));
+ context.tx[jj].current += ctx[ii].tx[jj].current;
+ }
+ }
- return ret;
+ print_metrics(&context);
}
View
18 metrics.h
@@ -27,24 +27,20 @@
#include <sys/time.h>
#include <stdint.h>
#include "config.h"
-#include "memcachetest.h"
#ifdef __cplusplus
extern "C" {
#endif
-enum TxnType { TX_GET, TX_SET, TX_ADD, TX_REPLACE, TX_APPEND, TX_PREPEND, TX_CAS };
+enum TxnType { TX_GET, TX_SET, TX_ADD, TX_REPLACE,
+ TX_APPEND, TX_PREPEND, TX_CAS };
+struct thread_context;
void record_tx(enum TxnType, hrtime_t, struct thread_context *);
-void record_error(enum TxnType, hrtime_t);
-struct ResultMetrics *calc_metrics(enum TxnType tx_type);
-
-struct TxnResult {
- hrtime_t respTime;
- struct TxnResult * next;
- struct TxnResult* left;
- struct TxnResult* right;
-};
+struct ResultMetrics *calc_metrics(enum TxnType tx_type,
+ struct thread_context *);
+void print_metrics(struct thread_context *);
+void print_aggregated_metrics(struct thread_context *, int);
struct ResultMetrics {
hrtime_t max_result;

0 comments on commit 6f8254d

Please sign in to comment.
Something went wrong with that request. Please try again.