summaryrefslogtreecommitdiff
path: root/tools/wrk/src/units.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/wrk/src/units.c')
-rw-r--r--tools/wrk/src/units.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/tools/wrk/src/units.c b/tools/wrk/src/units.c
new file mode 100644
index 0000000000..b9fc3c0fdf
--- /dev/null
+++ b/tools/wrk/src/units.c
@@ -0,0 +1,96 @@
+// Copyright (C) 2012 - Will Glozer. All rights reserved.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+#include <inttypes.h>
+
+#include "units.h"
+#include "aprintf.h"
+
+typedef struct {
+ int scale;
+ char *base;
+ char *units[];
+} units;
+
+units time_units_us = {
+ .scale = 1000,
+ .base = "us",
+ .units = { "ms", "s", NULL }
+};
+
+units time_units_s = {
+ .scale = 60,
+ .base = "s",
+ .units = { "m", "h", NULL }
+};
+
+units binary_units = {
+ .scale = 1024,
+ .base = "",
+ .units = { "K", "M", "G", "T", "P", NULL }
+};
+
+units metric_units = {
+ .scale = 1000,
+ .base = "",
+ .units = { "k", "M", "G", "T", "P", NULL }
+};
+
+static char *format_units(long double n, units *m, int p) {
+ long double amt = n, scale;
+ char *unit = m->base;
+ char *msg = NULL;
+
+ scale = m->scale * 0.85;
+
+ for (int i = 0; m->units[i+1] && amt >= scale; i++) {
+ amt /= m->scale;
+ unit = m->units[i];
+ }
+
+ aprintf(&msg, "%.*Lf%s", p, amt, unit);
+
+ return msg;
+}
+
+static int scan_units(char *s, uint64_t *n, units *m) {
+ uint64_t base, scale = 1;
+ char unit[3] = { 0, 0, 0 };
+ int i, c;
+
+ if ((c = sscanf(s, "%"SCNu64"%2s", &base, unit)) < 1) return -1;
+
+ if (c == 2) {
+ for (i = 0; m->units[i] != NULL; i++) {
+ scale *= m->scale;
+ if (!strncasecmp(unit, m->units[i], sizeof(unit))) break;
+ }
+ if (m->units[i] == NULL) return -1;
+ }
+
+ *n = base * scale;
+ return 0;
+}
+
+char *format_binary(long double n) {
+ return format_units(n, &binary_units, 2);
+}
+
+char *format_metric(long double n) {
+ return format_units(n, &metric_units, 2);
+}
+
+char *format_time_us(long double n) {
+ units *units = &time_units_us;
+ if (n >= 1000000.0) {
+ n /= 1000000.0;
+ units = &time_units_s;
+ }
+ return format_units(n, units, 2);
+}
+
+int scan_metric(char *s, uint64_t *n) {
+ return scan_units(s, n, &metric_units);
+}