Skip to content

Commit

Permalink
add option to print latency distribution
Browse files Browse the repository at this point in the history
  • Loading branch information
wg committed May 8, 2013
1 parent 05fcf7e commit d058222
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 23 deletions.
33 changes: 16 additions & 17 deletions src/stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,21 @@ void stats_record(stats *stats, uint64_t x) {
if (stats->index == stats->samples) stats->index = 0;
}

uint64_t stats_min(stats *stats) {
uint64_t min = 0;
for (uint64_t i = 0; i < stats->limit; i++) {
uint64_t x = stats->data[i];
if (x < min || min == 0) min = x;
}
return min;
static int stats_compare(const void *a, const void *b) {
uint64_t *x = (uint64_t *) a;
uint64_t *y = (uint64_t *) b;
return *x - *y;
}

uint64_t stats_max(stats *stats) {
uint64_t max = 0;
for (uint64_t i = 0; i < stats->limit; i++) {
uint64_t x = stats->data[i];
if (x > max || max == 0) max = x;
}
return max;
}
long double stats_summarize(stats *stats, int64_t *min, uint64_t *max) {
qsort(stats->data, stats->limit, sizeof(uint64_t), &stats_compare);

if (min) *min = stats->data[0];
if (max) *max = stats->data[stats->limit - 1];

long double stats_mean(stats *stats) {
uint64_t sum = 0;
if (stats->limit == 0) return 0.0;

uint64_t sum = 0;
for (uint64_t i = 0; i < stats->limit; i++) {
sum += stats->data[i];
}
Expand Down Expand Up @@ -71,3 +65,8 @@ long double stats_within_stdev(stats *stats, long double mean, long double stdev

return (sum / (long double) stats->limit) * 100;
}

uint64_t stats_percentile(stats *stats, long double p) {
uint64_t rank = round((p / 100.0) * stats->limit + 0.5);
return stats->data[rank - 1];
}
5 changes: 2 additions & 3 deletions src/stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ typedef struct {
stats *stats_alloc(uint64_t);
void stats_free(stats *);
void stats_record(stats *, uint64_t);
uint64_t stats_min(stats *);
uint64_t stats_max(stats *);
long double stats_mean(stats *);
long double stats_summarize(stats *, int64_t *, uint64_t *);
long double stats_stdev(stats *stats, long double);
long double stats_within_stdev(stats *, long double, long double, uint64_t);
uint64_t stats_percentile(stats *, long double);

#endif /* STATS_H */

26 changes: 23 additions & 3 deletions src/wrk.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand All @@ -33,6 +34,7 @@ static struct config {
uint64_t connections;
uint64_t duration;
uint64_t timeout;
bool latency;
} cfg;

static struct {
Expand Down Expand Up @@ -64,6 +66,7 @@ static void usage() {
" -t, --threads <N> Number of threads to use \n"
" \n"
" -H, --header <H> Add header to request \n"
" --latency Print latency statistics \n"
" --timeout <T> Socket/request timeout \n"
" -v, --version Print version details \n"
" \n"
Expand Down Expand Up @@ -187,6 +190,7 @@ int main(int argc, char **argv) {
print_stats_header();
print_stats("Latency", statistics.latency, format_time_us);
print_stats("Req/Sec", statistics.requests, format_metric);
if (cfg.latency) print_stats_latency(statistics.latency);

char *runtime_msg = format_time_us(runtime_us);

Expand Down Expand Up @@ -428,6 +432,7 @@ static struct option longopts[] = {
{ "duration", required_argument, NULL, 'd' },
{ "threads", required_argument, NULL, 't' },
{ "header", required_argument, NULL, 'H' },
{ "latency", no_argument, NULL, 'L' },
{ "timeout", required_argument, NULL, 'T' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'v' },
Expand All @@ -443,7 +448,7 @@ static int parse_args(struct config *cfg, char **url, char **headers, int argc,
cfg->duration = 10;
cfg->timeout = SOCKET_TIMEOUT_MS;

while ((c = getopt_long(argc, argv, "t:c:d:H:T:rv?", longopts, NULL)) != -1) {
while ((c = getopt_long(argc, argv, "t:c:d:H:T:Lrv?", longopts, NULL)) != -1) {
switch (c) {
case 't':
if (scan_metric(optarg, &cfg->threads)) return -1;
Expand All @@ -457,6 +462,9 @@ static int parse_args(struct config *cfg, char **url, char **headers, int argc,
case 'H':
*header++ = optarg;
break;
case 'L':
cfg->latency = true;
break;
case 'T':
if (scan_time(optarg, &cfg->timeout)) return -1;
cfg->timeout *= 1000;
Expand Down Expand Up @@ -506,8 +514,8 @@ static void print_units(long double n, char *(*fmt)(long double), int width) {
}

static void print_stats(char *name, stats *stats, char *(*fmt)(long double)) {
long double mean = stats_mean(stats);
long double max = stats_max(stats);
uint64_t max;
long double mean = stats_summarize(stats, NULL, &max);
long double stdev = stats_stdev(stats, mean);

printf(" %-10s", name);
Expand All @@ -516,3 +524,15 @@ static void print_stats(char *name, stats *stats, char *(*fmt)(long double)) {
print_units(max, fmt, 9);
printf("%8.2Lf%%\n", stats_within_stdev(stats, mean, stdev, 1));
}

static void print_stats_latency(stats *stats) {
long double percentiles[] = { 50.0, 75.0, 90.0, 99.0 };
printf(" Latency Distribution\n");
for (size_t i = 0; i < sizeof(percentiles) / sizeof(long double); i++) {
long double p = percentiles[i];
uint64_t n = stats_percentile(stats, p);
printf("%7.0Lf%%", p);
print_units(n, format_time_us, 10);
printf("\n");
}
}
1 change: 1 addition & 0 deletions src/wrk.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,6 @@ static char *format_request(char *, char *, char *, char **);
static int parse_args(struct config *, char **, char **, int, char **);
static void print_stats_header();
static void print_stats(char *, stats *, char *(*)(long double));
static void print_stats_latency(stats *);

#endif /* WRK_H */

0 comments on commit d058222

Please sign in to comment.