aboutsummaryrefslogtreecommitdiffstats
path: root/avg.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--avg.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/avg.c b/avg.c
new file mode 100644
index 0000000..4078c50
--- /dev/null
+++ b/avg.c
@@ -0,0 +1,94 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+/* TODO deal with machine and process suspension */
+
+
+static struct timespec write_average_begin_times[5];
+static off_t write_average_amounts[ELEMSOF(write_average_begin_times)] = {0};
+static int write_average_i = 0;
+
+
+static int
+was_write_average_overrun(int i, const struct timespec *now, int seconds)
+{
+ struct timespec diff;
+ libsimple_difftimespec(&diff, now, &write_average_begin_times[i]);
+ if (diff.tv_sec >= seconds)
+ return 1;
+ if (diff.tv_sec == seconds - 1 && diff.tv_nsec >= DECISECONDS(9))
+ return 1;
+ return 0;
+}
+
+
+static void
+shift_write_average(void)
+{
+ write_average_i--;
+ memmove(&write_average_begin_times[0], &write_average_begin_times[1],
+ (size_t)write_average_i * sizeof(*write_average_begin_times));
+ memmove(&write_average_amounts[0], &write_average_amounts[1],
+ (size_t)write_average_i * sizeof(*write_average_amounts));
+}
+
+
+void
+wravg_init(const struct timespec *start_time)
+{
+ write_average_begin_times[0] = *start_time;
+}
+
+
+void
+wravg_update_write(ssize_t amount)
+{
+ if (amount > 0)
+ write_average_amounts[write_average_i] += (off_t)amount;
+}
+
+
+void
+wravg_update_time(const struct timespec *now)
+{
+ if (was_write_average_overrun(write_average_i, now, 1)) {
+ write_average_i++;
+ if (write_average_i == ELEMSOF(write_average_amounts))
+ shift_write_average();
+ write_average_begin_times[write_average_i] = *now;
+ write_average_amounts[write_average_i] = 0;
+ }
+ while (write_average_i && was_write_average_overrun(0, now, (int)ELEMSOF(write_average_amounts)))
+ shift_write_average();
+}
+
+
+const char *
+wravg_get(const struct timespec *now)
+{
+ static char buf[512];
+
+ struct timespec write_average_time;
+ off_t write_average_sum = 0;
+ double write_average;
+ int i;
+
+ for (i = 0; i <= write_average_i; i++)
+ write_average_sum += write_average_amounts[i];
+
+ libsimple_difftimespec(&write_average_time, now, &write_average_begin_times[0]);
+
+ if (write_average_time.tv_sec < 0)
+ return "-";
+ if (write_average_time.tv_sec == 0 && write_average_time.tv_nsec < CENTISECONDS(10))
+ return "-";
+ if (write_average_sum == 0)
+ return "0";
+
+ write_average = (double)write_average_time.tv_nsec;
+ write_average /= WHOLE_SECOND;
+ write_average += (double)write_average_time.tv_sec;
+ write_average = (double)write_average_sum / write_average;
+ return humanbytespersecond(write_average, buf);
+}