aboutsummaryrefslogtreecommitdiffstats
path: root/stats.c
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-10-25 02:49:12 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-10-25 02:49:12 -0400
commit61af3de31a9a4d4928ebd468ce645b9596f46184 (patch)
tree5a3d700aa4ba2b70546a0614d3bcf1c9af2841cb /stats.c
downloadrng-tools-61af3de31a9a4d4928ebd468ce645b9596f46184.tar.gz
rng-tools-61af3de31a9a4d4928ebd468ce645b9596f46184.tar.xz
rng-tools-61af3de31a9a4d4928ebd468ce645b9596f46184.zip
Import rng-tools from private subversion repo.
Diffstat (limited to 'stats.c')
-rw-r--r--stats.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/stats.c b/stats.c
new file mode 100644
index 0000000..dbdac5d
--- /dev/null
+++ b/stats.c
@@ -0,0 +1,152 @@
+/*
+ * stats.c -- Statistics helpers
+ *
+ * Copyright (C) 2004 Henrique de Moraes Holschuh <hmh@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define _GNU_SOURCE
+
+#ifndef HAVE_CONFIG_H
+#error Invalid or missing autoconf build environment
+#endif
+
+#include "rng-tools-config.h"
+
+#include <unistd.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <time.h>
+#include <string.h>
+
+#include "fips.h"
+#include "stats.h"
+
+
+static char stat_prefix[20] = "";
+
+void set_stat_prefix(const char* prefix)
+{
+ stat_prefix[sizeof(stat_prefix)-1] = 0;
+ strncpy(stat_prefix, prefix, sizeof(stat_prefix)-1);
+}
+
+static void scale_mult_unit(char *unit, int unitsize,
+ const char *baseunit,
+ double *value_min,
+ double *value_avg,
+ double *value_max)
+{
+ int mult = 0;
+ char multchar[] = "KMGTPE";
+
+ while ((*value_min >= 1024.0) && (*value_avg >= 1024.0) &&
+ (*value_max >= 1024.0) && (mult < sizeof(multchar))) {
+ mult++;
+ *value_min = *value_min / 1024.0;
+ *value_max = *value_max / 1024.0;
+ *value_avg = *value_avg / 1024.0;
+ }
+ unit[unitsize-1] = 0;
+ if (mult)
+ snprintf(unit, unitsize, "%ci%s", multchar[mult-1], baseunit);
+ else
+ strncpy(unit, baseunit, unitsize);
+}
+
+/* Computes elapsed time in microseconds */
+uint64_t elapsed_time(struct timeval *start,
+ struct timeval *stop)
+{
+ uint64_t diff;
+
+ if (stop->tv_sec < start->tv_sec) return 0;
+
+ diff = (stop->tv_sec - start->tv_sec) * 1000000ULL;
+ if (stop->tv_usec > start->tv_usec) {
+ diff += stop->tv_usec - start->tv_usec;
+ } else {
+ diff -= start->tv_usec - stop->tv_usec;
+ }
+
+ return diff;
+}
+
+/* Updates min-max stat */
+void update_stat(struct rng_stat *stat, uint64_t value)
+{
+ uint64_t overflow = stat->num_samples;
+
+ if ((stat->min == 0 ) || (value < stat->min)) stat->min = value;
+ if (value > stat->max) stat->max = value;
+ if (++stat->num_samples > overflow) {
+ stat->sum += value;
+ } else {
+ stat->sum = value;
+ stat->num_samples = 1;
+ }
+}
+
+char *dump_stat_counter(char *buf, int size,
+ const char *msg, uint64_t value)
+{
+ buf[size-1] = 0;
+ snprintf(buf, size-1, "%s%s: %llu", stat_prefix, msg, value);
+
+ return buf;
+}
+
+char *dump_stat_stat(char *buf, int size,
+ const char *msg, const char *unit, struct rng_stat *stat)
+{
+ double avg = 0.0;
+
+ if (stat->num_samples > 0)
+ avg = (double)stat->sum / stat->num_samples;
+
+ buf[size-1] = 0;
+ snprintf(buf, size-1, "%s%s: (min=%llu; avg=%.3f; max=%llu)%s",
+ stat_prefix, msg, stat->min, avg, stat->max, unit);
+
+ return buf;
+}
+
+char *dump_stat_bw(char *buf, int size,
+ const char *msg, const char *unit,
+ struct rng_stat *stat,
+ uint64_t blocksize)
+{
+ char unitscaled[20];
+ double bw_avg = 0.0, bw_min = 0.0, bw_max = 0.0;
+
+ if (stat->max > 0)
+ bw_min = (1000000.0 * blocksize) / stat->max;
+ if (stat->min > 0)
+ bw_max = (1000000.0 * blocksize) / stat->min;
+ if (stat->num_samples > 0)
+ bw_avg = (1000000.0 * blocksize * stat->num_samples) / stat->sum;
+
+ scale_mult_unit(unitscaled, sizeof(unitscaled), unit,
+ &bw_min, &bw_avg, &bw_max);
+
+ buf[size-1] = 0;
+ snprintf(buf, size-1, "%s%s: (min=%.3f; avg=%.3f; max=%.3f)%s/s",
+ stat_prefix, msg, bw_min, bw_avg, bw_max, unitscaled);
+
+ return buf;
+}
+