brintos

brintos / linux-shallow public Read only

0
0
Text · 4.3 KiB · dc6493f Raw
161 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2/*3 * bch2_time_stats - collect statistics on events that have a duration, with nicely4 * formatted textual output on demand5 *6 * - percpu buffering of event collection: cheap enough to shotgun7 *   everywhere without worrying about overhead8 *9 * tracks:10 *  - number of events11 *  - maximum event duration ever seen12 *  - sum of all event durations13 *  - average event duration, standard and weighted14 *  - standard deviation of event durations, standard and weighted15 * and analagous statistics for the frequency of events16 *17 * We provide both mean and weighted mean (exponentially weighted), and standard18 * deviation and weighted standard deviation, to give an efficient-to-compute19 * view of current behaviour versus. average behaviour - "did this event source20 * just become wonky, or is this typical?".21 *22 * Particularly useful for tracking down latency issues.23 */24#ifndef _BCACHEFS_TIME_STATS_H25#define _BCACHEFS_TIME_STATS_H26 27#include <linux/sched/clock.h>28#include <linux/spinlock_types.h>29#include <linux/string.h>30 31#include "mean_and_variance.h"32 33struct time_unit {34	const char	*name;35	u64		nsecs;36};37 38/*39 * given a nanosecond value, pick the preferred time units for printing:40 */41const struct time_unit *bch2_pick_time_units(u64 ns);42 43/*44 * quantiles - do not use:45 *46 * Only enabled if bch2_time_stats->quantiles_enabled has been manually set - don't47 * use in new code.48 */49 50#define NR_QUANTILES	1551#define QUANTILE_IDX(i)	inorder_to_eytzinger0(i, NR_QUANTILES)52#define QUANTILE_FIRST	eytzinger0_first(NR_QUANTILES)53#define QUANTILE_LAST	eytzinger0_last(NR_QUANTILES)54 55struct quantiles {56	struct quantile_entry {57		u64	m;58		u64	step;59	}		entries[NR_QUANTILES];60};61 62struct time_stat_buffer {63	unsigned	nr;64	struct time_stat_buffer_entry {65		u64	start;66		u64	end;67	}		entries[31];68};69 70struct bch2_time_stats {71	spinlock_t	lock;72	bool		have_quantiles;73	struct time_stat_buffer __percpu *buffer;74	/* all fields are in nanoseconds */75	u64             min_duration;76	u64		max_duration;77	u64		total_duration;78	u64             max_freq;79	u64             min_freq;80	u64		last_event;81	u64		last_event_start;82 83	struct mean_and_variance	  duration_stats;84	struct mean_and_variance	  freq_stats;85 86/* default weight for weighted mean and variance calculations */87#define TIME_STATS_MV_WEIGHT	888 89	struct mean_and_variance_weighted duration_stats_weighted;90	struct mean_and_variance_weighted freq_stats_weighted;91};92 93struct bch2_time_stats_quantiles {94	struct bch2_time_stats	stats;95	struct quantiles	quantiles;96};97 98static inline struct quantiles *time_stats_to_quantiles(struct bch2_time_stats *stats)99{100	return stats->have_quantiles101		? &container_of(stats, struct bch2_time_stats_quantiles, stats)->quantiles102		: NULL;103}104 105void __bch2_time_stats_clear_buffer(struct bch2_time_stats *, struct time_stat_buffer *);106void __bch2_time_stats_update(struct bch2_time_stats *stats, u64, u64);107 108/**109 * time_stats_update - collect a new event being tracked110 *111 * @stats	- bch2_time_stats to update112 * @start	- start time of event, recorded with local_clock()113 *114 * The end duration of the event will be the current time115 */116static inline void bch2_time_stats_update(struct bch2_time_stats *stats, u64 start)117{118	__bch2_time_stats_update(stats, start, local_clock());119}120 121/**122 * track_event_change - track state change events123 *124 * @stats	- bch2_time_stats to update125 * @v		- new state, true or false126 *127 * Use this when tracking time stats for state changes, i.e. resource X becoming128 * blocked/unblocked.129 */130static inline bool track_event_change(struct bch2_time_stats *stats, bool v)131{132	if (v != !!stats->last_event_start) {133		if (!v) {134			bch2_time_stats_update(stats, stats->last_event_start);135			stats->last_event_start = 0;136		} else {137			stats->last_event_start = local_clock() ?: 1;138			return true;139		}140	}141 142	return false;143}144 145void bch2_time_stats_reset(struct bch2_time_stats *);146void bch2_time_stats_exit(struct bch2_time_stats *);147void bch2_time_stats_init(struct bch2_time_stats *);148 149static inline void bch2_time_stats_quantiles_exit(struct bch2_time_stats_quantiles *statq)150{151	bch2_time_stats_exit(&statq->stats);152}153static inline void bch2_time_stats_quantiles_init(struct bch2_time_stats_quantiles *statq)154{155	bch2_time_stats_init(&statq->stats);156	statq->stats.have_quantiles = true;157	memset(&statq->quantiles, 0, sizeof(statq->quantiles));158}159 160#endif /* _BCACHEFS_TIME_STATS_H */161