Skip to contentSkip to conversation

timer_stats slimmed down: statistics prereq, keys

RFC PATCH In review Martin Peschke 1 participant 1 message Apr 14, 2007

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 3/4 timer_stats slimmed down: statistics prereq, keys

Client have statistics be updated by reporting (X, Y) data pairs, with X being a certain characteristic and Y a qualifier, e.g. (request size, number of new requests of this size). In a way, the role of X is the one of a primary key for statistics entries, if the statistic comprises several "baskets" (think of histograms).

X used to be an integer value. For several applications it might be useful to allow X to be an opaque binary blob. This way, clients can use structures with several members as keys.

Clients are called back when statistics entries are printed, so that they can label entries using their interpretation of a key.

---

 include/linux/statistic.h |  132 ++++++++++++++++++++++++++++++-
 lib/statistic.c           |  191 +++++++++++++++++++++++++++++++++++-----------
 2 files changed, 272 insertions(+), 51 deletions(-)
include/linux/statistic.h +126 -6
Index: linux/include/linux/statistic.h
===================================================================
@@ -1,11 +1,9 @@
 /*
- * include/linux/statistic.h
+ * statistics facility
  *
- * Statistics facility
+ * Copyright IBM Corp. 2005, 2007
  *
- * (C) Copyright IBM Corp. 2005, 2006
- *
- * Author(s): Martin Peschke <[email protected]>
+ * Author(s): Martin Peschke <[email protected]>
  *
  * 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
@@ -35,6 +33,7 @@
  * @x_unit: pointer to string describing unit of X of (X, Y) data pair
  * @y_unit: pointer to string describing unit of Y of (X, Y) data pair
  * @flags: bits describing special settings
+ * @key_size: in bytes, only applicable if STATISTIC_FLAGS_KEY is used
  * @defaults: pointer to string describing defaults setting for attributes
  *
  * Exploiters must setup an array of struct statistic_info for a
@@ -56,6 +55,14 @@ struct statistic_info {
 #define STATISTIC_FLAGS_NOINCR	0x01	/* no incremental data */
 #define STATISTIC_FLAGS_NOFLEX	0x02	/* type can't be altered by user */
 #define STATISTIC_FLAGS_LABEL	0x04	/* client want's to label buckets */
+#define _STATISTIC_FLAGS_KEY	0x08	/* client uses opaque binary key
+					   instead of integer
+					   (flag not for direct use) */
+#define STATISTIC_FLAGS_KEY	_STATISTIC_FLAGS_KEY | STATISTIC_FLAGS_LABEL
+					/* client uses opaque binary key and
+					   labels buckets based on its
+					   interpretation of keys */
+	int  key_size;
 	char *defaults;
 };
 
@@ -89,6 +96,7 @@ struct statistic {
 	u64			 started;
 	u64			 stopped;
 	u64			 age;
+	int			 key_size; /* FIXME: not pretty */
 	union {
 		struct {
 			s64 range_min;
@@ -125,7 +133,7 @@ struct statistic_interface {
 	int			 number;
 	int			(*pull)(struct statistic_interface *interface);
 	void			(*label)(struct statistic_interface *interface,
-					 int i, s64 value,
+					 int i, void *key,
 					 struct seq_file *seq);
 	void			*private;
 };
@@ -136,9 +144,12 @@ extern int statistic_create(struct stati
 extern int statistic_remove(struct statistic_interface *);
 
 extern void statistic_set(struct statistic *, int, s64, u64);
+extern void statistic_set_key(struct statistic *, int, void *, u64);
 
 extern void _statistic_add(struct statistic *, int, s64, u64);
 extern void statistic_add(struct statistic *, int, s64, u64);
+extern void _statistic_add_key(struct statistic *, int, void *, u64);
+extern void statistic_add_key(struct statistic *, int, void *, u64);
 
 /*
  * Clients are not supposed to call these directly.
@@ -152,6 +163,8 @@ extern void statistic_add_histogram_lin(
 extern void statistic_add_histogram_log2(struct statistic *, s64, u64);
 extern void statistic_add_sparse(struct statistic *, s64, u64);
 
+extern void statistic_kadd_sparse(struct statistic *, void *, u64);
+
 /**
  * _statistic_add_as - update statistic with incremental data in (X, Y) pair
  * @type: data proessing mode to be used (must match statistic_info::defaults)
@@ -230,6 +243,76 @@ static inline void statistic_add_as(int 
 	local_irq_restore(flags);
 }
 
+/**
+ * _statistic_add_as_key - update statistic with incremental data in (X, Y) pair
+ * @type: data proessing mode to be used (must match statistic_info::defaults)
+ * @stat: struct statistic array
+ * @i: index of statistic to be updated
+ * @key: X (opaque binary blob)
+ * @incr: Y
+ *
+ * The actual processing of the (X, Y) data pair is determined by the current
+ * definition applied to the statistic. See Documentation/statistics.txt.
+ *
+ * This function is faster than _statistic_add() because the data
+ * processing mode is already determined at compile time.
+ * Use this when you feel that the perfomance gain outweighs the loss
+ * of flexibility for your particular statistic.
+ *
+ * This variant leaves protecting per-cpu data to clients. It is preferred
+ * whenever clients update several statistics of the same entity in one go.
+ *
+ * You may want to use _statistic_inc_as_key() for (X, 1) data pairs.
+ */
+static inline void _statistic_add_as_key(int type, struct statistic *stat,
+					 int i, void *key, u64 incr)
+{
+	if (stat[i].state == STATISTIC_STATE_ON) {
+		switch (type) {
+		case STAT_CNTR_INC:
+		case STAT_CNTR_PROD:
+		case STAT_UTIL:
+		case STAT_HGRAM_LIN:
+		case STAT_HGRAM_LOG2:
+			_statistic_add_as(type, stat, i, 0, incr);
+			break;
+		case STAT_SPARSE:
+			statistic_kadd_sparse(&stat[i], key, incr);
+			break;
+		}
+	}
+}
+
+/**
+ * statistic_add_as_key - update statistic with incremental data in (X, Y) pair
+ * @type: data proessing mode to be used (must match statistic_info::defaults)
+ * @stat: struct statistic array
+ * @i: index of statistic to be updated
+ * @key: X (opaque binary blob)
+ * @incr: Y
+ *
+ * The actual processing of the (X, Y) data pair is determined by the current
+ * the definition applied to the statistic. See Documentation/statistics.txt.
+ *
+ * This function is faster than statistic_add() because the data
+ * processing mode is already determined at compile time.
+ * Use this when you feel that the perfomance gain outweighs the loss
+ * of flexibility for your particular statistic.
+ *
+ * This variant takes care of protecting per-cpu data. It is preferred whenever
+ * clients don't update several statistics of the same entity in one go.
+ *
+ * You may want to use statistic_inc_as_key() for (X, 1) data pairs.
+ */
+static inline void statistic_add_as_key(int type, struct statistic *stat,
+					int i, void *key, u64 incr)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+	_statistic_add_as_key(type, stat, i, key, incr);
+	local_irq_restore(flags);
+}
+
 #else /* !CONFIG_STATISTICS */
 /* These NOP functions unburden clients from handling !CONFIG_STATISTICS. */
 
@@ -269,6 +352,31 @@ static inline void statistic_add_as(int 
 {
 }
 
+static inline void statistic_set_key(struct statistic *stat, int i,
+				     void *key, u64 total)
+{
+}
+
+static inline void _statistic_add_key(struct statistic *stat, int i,
+				      void *key, u64 incr)
+{
+}
+
+static inline void statistic_add_key(struct statistic *stat, int i,
+				     void *key, u64 incr)
+{
+}
+
+static inline void _statistic_add_as_key(int type, struct statistic *stat,
+					 int i, void *key, u64 incr)
+{
+}
+
+static inline void statistic_add_as_key(int type, struct statistic *stat,
+					int i, void *key, u64 incr)
+{
+}
+
 #endif /* CONFIG_STATISTICS */
 
 #define _statistic_inc(stat, i, value) \
@@ -283,4 +391,16 @@ static inline void statistic_add_as(int 
 #define statistic_inc_as(type, stat, i, value) \
 	statistic_add_as(type, stat, i, value, 1)
 
+#define _statistic_inc_key(stat, i, key) \
+	_statistic_add_key(stat, i, key, 1)
+
+#define statistic_inc_key(stat, i, key) \
+	statistic_add_key(stat, i, key, 1)
+
+#define _statistic_inc_as_key(type, stat, i, key) \
+	_statistic_add_as_key(type, stat, i, key, 1)
+
+#define statistic_inc_as_key(type, stat, i, key) \
+	statistic_add_as_key(type, stat, i, key, 1)
+
 #endif /* STATISTIC_H */
lib/statistic.c +146 -45

310 lines not on this page · raw message