diff options
author | Daniel Hill <daniel@gluo.nz> | 2022-08-12 09:03:28 +1200 |
---|---|---|
committer | Daniel Hill <daniel@gluo.nz> | 2022-09-04 16:41:38 +1200 |
commit | 2604a8e4bbac50c014007bee9b1bf1a84ec1fa13 (patch) | |
tree | ca031fdaf7b9c3c4482e69614af486a8f84c1758 | |
parent | c80870627dd4a4c0719d0f8fa2c3d432c446dbac (diff) |
bcachefs: time stats now uses the mean_and_variance module.
Signed-off-by: Daniel Hill <daniel@gluo.nz>
-rw-r--r-- | fs/bcachefs/Kconfig | 1 | ||||
-rw-r--r-- | fs/bcachefs/util.c | 103 | ||||
-rw-r--r-- | fs/bcachefs/util.h | 8 |
3 files changed, 91 insertions, 21 deletions
diff --git a/fs/bcachefs/Kconfig b/fs/bcachefs/Kconfig index 008886967841..2b9387ac1bca 100644 --- a/fs/bcachefs/Kconfig +++ b/fs/bcachefs/Kconfig @@ -23,6 +23,7 @@ config BCACHEFS_FS select XXHASH select SRCU select SYMBOLIC_ERRNAME + select MEAN_AND_VARIANCE help The bcachefs filesystem - a modern, copy on write filesystem, with support for multiple devices, compression, checksumming, etc. diff --git a/fs/bcachefs/util.c b/fs/bcachefs/util.c index 42da6623d815..26c4c4db120a 100644 --- a/fs/bcachefs/util.c +++ b/fs/bcachefs/util.c @@ -21,6 +21,7 @@ #include <linux/string.h> #include <linux/types.h> #include <linux/sched/clock.h> +#include <linux/mean_and_variance.h> #include "eytzinger.h" #include "util.h" @@ -279,22 +280,18 @@ void bch2_prt_u64_binary(struct printbuf *out, u64 v, unsigned nr_bits) static void bch2_time_stats_update_one(struct time_stats *stats, u64 start, u64 end) { - u64 duration, freq; + u64 duration, frequency; duration = time_after64(end, start) ? end - start : 0; - freq = time_after64(end, stats->last_event) + frequency = time_after64(end, stats->last_event) ? end - stats->last_event : 0; - stats->count++; + stats->duration_stats = mean_and_variance_update(stats->duration_stats, duration); + stats->duration_stats_weighted = mean_and_variance_weighted_update(stats->duration_stats_weighted, duration); - stats->average_duration = stats->average_duration - ? ewma_add(stats->average_duration, duration, 6) - : duration; - - stats->average_frequency = stats->average_frequency - ? ewma_add(stats->average_frequency, freq, 6) - : freq; + stats->frequency_stats = mean_and_variance_update(stats->frequency_stats, frequency); + stats->frequency_stats_weighted = mean_and_variance_weighted_update(stats->frequency_stats_weighted, frequency); stats->max_duration = max(stats->max_duration, duration); @@ -311,8 +308,8 @@ void __bch2_time_stats_update(struct time_stats *stats, u64 start, u64 end) spin_lock_irqsave(&stats->lock, flags); bch2_time_stats_update_one(stats, start, end); - if (stats->average_frequency < 32 && - stats->count > 1024) + if (mean_and_variance_get_mean(stats->frequency_stats) < 32 && + stats->duration_stats.n > 1024) stats->buffer = alloc_percpu_gfp(struct time_stat_buffer, GFP_ATOMIC); @@ -378,28 +375,96 @@ static void pr_time_units(struct printbuf *out, u64 ns) void bch2_time_stats_to_text(struct printbuf *out, struct time_stats *stats) { const struct time_unit *u; - u64 freq = READ_ONCE(stats->average_frequency); + s64 freq = mean_and_variance_get_mean(stats->frequency_stats); u64 q, last_q = 0; int i; prt_printf(out, "count:\t\t%llu", - stats->count); + stats->duration_stats.n); prt_newline(out); + prt_printf(out, "rate:\t\t%llu/sec", freq ? div64_u64(NSEC_PER_SEC, freq) : 0); + prt_newline(out); + prt_printf(out, "standard:"); + printbuf_indent_add(out, 2); + printbuf_tabstop_push(out, out->indent + 18); - prt_printf(out, "frequency:\t"); + prt_newline(out); + prt_printf(out, "avg frequency:"); + prt_tab(out); pr_time_units(out, freq); prt_newline(out); - prt_printf(out, "avg duration:\t"); - pr_time_units(out, stats->average_duration); + prt_printf(out, "stddev frequency:"); + prt_tab(out); + pr_time_units(out, mean_and_variance_get_stddev(stats->frequency_stats)); + + printbuf_tabstop_pop(out); + printbuf_indent_sub(out, 2); + + prt_newline(out); + + prt_printf(out, "weighted:"); + printbuf_indent_add(out, 2); + printbuf_tabstop_push(out, out->indent + 18); + + prt_newline(out); + prt_printf(out, "avg frequency:"); + prt_tab(out); + pr_time_units(out, mean_and_variance_weighted_get_mean(stats->frequency_stats_weighted)); + + prt_newline(out); + prt_printf(out, "stddev frequency:"); + prt_tab(out); + pr_time_units(out, mean_and_variance_weighted_get_stddev(stats->frequency_stats_weighted)); + + printbuf_indent_sub(out, 2); + + prt_newline(out); + prt_printf(out, "standard:"); + printbuf_indent_add(out, 2); + printbuf_tabstop_push(out, out->indent + 18); prt_newline(out); - prt_printf(out, "max duration:\t"); + prt_printf(out, "avg duration:"); + prt_tab(out); + pr_time_units(out, mean_and_variance_get_mean(stats->duration_stats)); + + prt_newline(out); + prt_printf(out, "stddev duration:"); + prt_tab(out); + pr_time_units(out, mean_and_variance_get_stddev(stats->duration_stats)); + + printbuf_tabstop_pop(out); + printbuf_indent_sub(out, 2); + + prt_newline(out); + + prt_printf(out, "weighted:"); + printbuf_indent_add(out, 2); + printbuf_tabstop_push(out, out->indent + 18); + + prt_newline(out); + prt_printf(out, "avg duration:"); + prt_tab(out); + pr_time_units(out, mean_and_variance_weighted_get_mean(stats->duration_stats_weighted)); + + prt_newline(out); + prt_printf(out, "stddev duration:"); + prt_tab(out); + pr_time_units(out, mean_and_variance_weighted_get_stddev(stats->duration_stats_weighted)); + + printbuf_indent_sub(out, 2); + + prt_newline(out); + prt_printf(out, "max duration:"); + prt_tab(out); pr_time_units(out, stats->max_duration); + printbuf_tabstop_pop(out); + i = eytzinger0_first(NR_QUANTILES); u = pick_time_units(stats->quantiles.entries[i].m); @@ -425,6 +490,8 @@ void bch2_time_stats_exit(struct time_stats *stats) void bch2_time_stats_init(struct time_stats *stats) { memset(stats, 0, sizeof(*stats)); + stats->duration_stats_weighted.w = 8; + stats->frequency_stats_weighted.w = 8; spin_lock_init(&stats->lock); } diff --git a/fs/bcachefs/util.h b/fs/bcachefs/util.h index ab7e43d4bf8b..6980ae9f79d8 100644 --- a/fs/bcachefs/util.h +++ b/fs/bcachefs/util.h @@ -18,6 +18,7 @@ #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/workqueue.h> +#include <linux/mean_and_variance.h> struct closure; @@ -377,14 +378,15 @@ struct time_stat_buffer { struct time_stats { spinlock_t lock; - u64 count; /* all fields are in nanoseconds */ - u64 average_duration; - u64 average_frequency; u64 max_duration; u64 last_event; struct quantiles quantiles; + struct mean_and_variance duration_stats; + struct mean_and_variance_weighted duration_stats_weighted; + struct mean_and_variance frequency_stats; + struct mean_and_variance_weighted frequency_stats_weighted; struct time_stat_buffer __percpu *buffer; }; |