diff mbox series

libtraceeval: Move traceeval-hist.h to traceeval.h

Message ID 20230929081059.47c45ea8@rorschach.local.home (mailing list archive)
State Superseded
Headers show
Series libtraceeval: Move traceeval-hist.h to traceeval.h | expand

Commit Message

Steven Rostedt Sept. 29, 2023, 12:10 p.m. UTC
From: "Steven Rostedt (Google)" <rostedt@goodmis.org>

Now that the API of the new histogram logic of libtraceeval is rather
stable, we can now remove the old version and replace it with the new
version. The traceeval-hist.h was just a tempory header until it was to
a point that it should be the default. It now is at that point. Remove
the old code of the histogram and use the new code.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 include/traceeval-hist.h | 245 ------------
 include/traceeval.h      | 327 +++++++++++-----
 src/trace-analysis.c     | 805 ---------------------------------------
 3 files changed, 226 insertions(+), 1151 deletions(-)
 delete mode 100644 include/traceeval-hist.h
 delete mode 100644 src/trace-analysis.c
diff mbox series

Patch

diff --git a/include/traceeval-hist.h b/include/traceeval-hist.h
deleted file mode 100644
index cd089b2..0000000
--- a/include/traceeval-hist.h
+++ /dev/null
@@ -1,245 +0,0 @@ 
-/* SPDX-License-Identifier: MIT */
-/*
- * libtraceeval histogram interface.
- *
- * Copyright (C) 2023 Google Inc, Steven Rostedt <rostedt@goodmis.org>
- * Copyright (C) 2023 Google Inc, Stevie Alvarez <stevie.6strings@gmail.com>
- */
-#ifndef __LIBTRACEEVAL_HIST_H__
-#define __LIBTRACEEVAL_HIST_H__
-
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdbool.h>
-
-/* Data definition interfaces */
-
-/* Field name/descriptor for number of hits */
-#define TRACEEVAL_VAL_HITS ((const char *)(-1UL))
-
-#define TRACEEVAL_ARRAY_SIZE(data)	(sizeof(data) / sizeof((data)[0]))
-
-/* Data type distinguishers */
-enum traceeval_data_type {
-	TRACEEVAL_TYPE_NONE,
-	TRACEEVAL_TYPE_NUMBER_8,
-	TRACEEVAL_TYPE_NUMBER_16,
-	TRACEEVAL_TYPE_NUMBER_32,
-	TRACEEVAL_TYPE_NUMBER_64,
-	TRACEEVAL_TYPE_NUMBER,
-	TRACEEVAL_TYPE_POINTER,
-	TRACEEVAL_TYPE_STRING,
-};
-
-/* Statistics specification flags */
-enum traceeval_flags {
-	TRACEEVAL_FL_KEY		= (1 << 0),
-	TRACEEVAL_FL_VALUE		= (1 << 1),
-	TRACEEVAL_FL_SIGNED		= (1 << 2),
-	TRACEEVAL_FL_TIMESTAMP		= (1 << 3),
-	TRACEEVAL_FL_STAT		= (1 << 4),
-};
-
-/*
- * Trace data entry for a traceeval histogram
- * Constitutes keys and values.
- */
-struct traceeval_data {
-	enum traceeval_data_type		type;
-	union {
-		char				*string;
-		const char			*cstring;
-		void				*pointer;
-		unsigned long			number;
-		unsigned long long		number_64;
-		unsigned int			number_32;
-		unsigned short			number_16;
-		unsigned char			number_8;
-	};
-};
-
-#define __TRACEEVAL_DATA(data_type, member, data)			\
-	{  .type = TRACEEVAL_TYPE_##data_type, .member = (data) }
-
-#define DEFINE_TRACEEVAL_NUMBER(data)	   __TRACEEVAL_DATA(NUMBER, number, data)
-#define DEFINE_TRACEEVAL_NUMBER_8(data)	   __TRACEEVAL_DATA(NUMBER_8, number_8, data)
-#define DEFINE_TRACEEVAL_NUMBER_16(data)   __TRACEEVAL_DATA(NUMBER_16, number_16, data)
-#define DEFINE_TRACEEVAL_NUMBER_32(data)   __TRACEEVAL_DATA(NUMBER_32, number_32, data)
-#define DEFINE_TRACEEVAL_NUMBER_64(data)   __TRACEEVAL_DATA(NUMBER_64, number_64, data)
-#define DEFINE_TRACEEVAL_STRING(data)	   __TRACEEVAL_DATA(STRING, string, data)
-#define DEFINE_TRACEEVAL_CSTRING(data)	   __TRACEEVAL_DATA(STRING, cstring, data)
-#define DEFINE_TRACEEVAL_POINTER(data)	   __TRACEEVAL_DATA(POINTER, pointer, data)
-
-#define __TRACEEVAL_SET(data, data_type, member, val)		\
-	do {							\
-		(data).type = TRACEEVAL_TYPE_##data_type;	\
-		(data).member = (val);				\
-	} while (0)
-
-#define TRACEEVAL_SET_NUMBER(data, val)	     __TRACEEVAL_SET(data, NUMBER, number, val)
-#define TRACEEVAL_SET_NUMBER_8(data, val)    __TRACEEVAL_SET(data, NUMBER_8, number_8, val)
-#define TRACEEVAL_SET_NUMBER_16(data, val)   __TRACEEVAL_SET(data, NUMBER_16, number_16, val)
-#define TRACEEVAL_SET_NUMBER_32(data, val)   __TRACEEVAL_SET(data, NUMBER_32, number_32, val)
-#define TRACEEVAL_SET_NUMBER_64(data, val)   __TRACEEVAL_SET(data, NUMBER_64, number_64, val)
-#define TRACEEVAL_SET_STRING(data, val)	     __TRACEEVAL_SET(data, STRING, string, val)
-#define TRACEEVAL_SET_CSTRING(data, val)     __TRACEEVAL_SET(data, STRING, cstring, val)
-#define TRACEEVAL_SET_POINTER(data, val)     __TRACEEVAL_SET(data, POINTER, pointer, val)
-
-struct traceeval_type;
-struct traceeval;
-
-/* release function callback on traceeval_data */
-typedef void (*traceeval_data_release_fn)(const struct traceeval_type *type,
-					  struct traceeval_data *data);
-
-/* compare function callback to compare traceeval_data */
-typedef int (*traceeval_data_cmp_fn)(struct traceeval *teval,
-				     const struct traceeval_type *type,
-				     const struct traceeval_data *A,
-				     const struct traceeval_data *B);
-
-/* make a unique value */
-typedef int (*traceeval_data_hash_fn)(struct traceeval *teval,
-				      const struct traceeval_type *type,
-				      const struct traceeval_data *data);
-
-typedef int (*traceeval_data_copy_fn)(const struct traceeval_type *type,
-				      struct traceeval_data *dst,
-				      const struct traceeval_data *src);
-
-typedef int (*traceeval_cmp_fn)(struct traceeval *teval,
-				const struct traceeval_data *Akeys,
-				const struct traceeval_data *Avals,
-				const struct traceeval_data *Bkeys,
-				const struct traceeval_data *Bvals,
-				void *data);
-
-/*
- * struct traceeval_type - Describes the type of a traceevent_data instance
- * @type: The enum type that describes the traceeval_data
- * @name: The string name of the traceeval_data
- * @flags: flags to describe the traceeval_data
- * @id: User specified identifier
- * @release: An optional callback for when the data is being released
- * @cmp: An optional callback to specify a way to compare the type
- *
- * The traceeval_type structure defines expectations for a corresponding
- * traceeval_data instance for a traceeval histogram instance. Used to
- * describe both keys and values.
- *
- * The @id field is an optional value in case the user has multiple struct
- * traceeval_type instances and needs to distinguish between them into
- * 'sub-types'.
- *
- * For flexibility, @cmp() and @release() take a struct traceeval_type
- * instance. This allows the user to handle pointer types.
- * It may also be used for other types if the default cmp() or release()
- * need to be overridden. Note for string types, even if the release()
- * is called, the string freeing is still taken care of by the traceeval
- * infrastructure.
- *
- * The @id field is a user specified field that may allow the same callback
- * to be used by multiple types and not needing to do a strcmp() against the
- * name (could be used for switch statements).
- *
- * @cmp() is used to override the default compare of a type. This is
- * required to pointer types. It should return 0 on equality, 1 if the first
- * argument is greater than the second, -1 for the other way around,
- * and -2 on error.
- *
- * @release() is called when a data element is being released (or freed).
- */
-struct traceeval_type {
-	char				*name;
-	enum traceeval_data_type	type;
-	size_t				flags;
-	size_t				index;
-	size_t				id;
-	traceeval_data_release_fn	release;
-	traceeval_data_cmp_fn		cmp;
-	traceeval_data_copy_fn		copy;
-	traceeval_data_hash_fn		hash;
-};
-
-/* Statistics about a given entry element */
-struct traceeval_stat;
-
-/* Iterator over aggregated data */
-struct traceeval_iterator;
-
-struct traceeval;
-
-/* Histogram interfaces */
-
-#define traceeval_init(keys, vals)					\
-	traceeval_init_size(keys, vals,					\
-			    TRACEEVAL_ARRAY_SIZE(keys),			\
-			    (void *)vals == NULL ?  0 : TRACEEVAL_ARRAY_SIZE(vals))
-
-#define traceeval_init_size(keys, vals, nr_keys, nr_vals)		\
-	traceeval_init_data_size(keys, vals, nr_keys, nr_vals,		\
-				 sizeof(struct traceeval_type),		\
-				 sizeof(struct traceeval_data))
-
-struct traceeval *traceeval_init_data_size(struct traceeval_type *keys,
-					   struct traceeval_type *vals,
-					   size_t nr_keys, size_t nr_vals,
-					   size_t sizeof_type, size_t sizeof_data);
-
-void traceeval_release(struct traceeval *teval);
-
-int traceeval_insert_size(struct traceeval *teval,
-			  const struct traceeval_data *keys, size_t nr_keys,
-			  const struct traceeval_data *vals, size_t nr_vals);
-
-#define traceeval_insert(teval, keys, vals)				\
-	traceeval_insert_size(teval, keys, TRACEEVAL_ARRAY_SIZE(keys), \
-			      vals, (void *)vals == NULL ? 0 : TRACEEVAL_ARRAY_SIZE(vals))
-
-int traceeval_remove_size(struct traceeval *teval,
-			  const struct traceeval_data *keys, size_t nr_keys);
-
-#define traceeval_remove(teval, keys)					\
-	traceeval_remove_size(teval, keys, TRACEEVAL_ARRAY_SIZE(keys))
-
-int traceeval_query_size(struct traceeval *teval, const struct traceeval_data *keys,
-			 size_t nr_keys, const struct traceeval_data **results);
-
-#define traceeval_query(teval, keys, results)				\
-	traceeval_query_size(teval, keys, TRACEEVAL_ARRAY_SIZE(keys), results)
-
-void traceeval_results_release(struct traceeval *teval,
-			       const struct traceeval_data *results);
-
-size_t traceeval_count(struct traceeval *teval);
-
-#define traceeval_stat(teval, keys, type)				\
-	traceeval_stat_size(teval, keys, TRACEEVAL_ARRAY_SIZE(keys), type)
-
-struct traceeval_stat *traceeval_stat_size(struct traceeval *teval,
-					   const struct traceeval_data *keys,
-					   size_t nr_keys,
-					   struct traceeval_type *type);
-
-unsigned long long traceeval_stat_max(struct traceeval_stat *stat);
-unsigned long long traceeval_stat_min(struct traceeval_stat *stat);
-unsigned long long traceeval_stat_total(struct traceeval_stat *stat);
-unsigned long long traceeval_stat_count(struct traceeval_stat *stat);
-
-struct traceeval_iterator *traceeval_iterator_get(struct traceeval *teval);
-void traceeval_iterator_put(struct traceeval_iterator *iter);
-int traceeval_iterator_sort(struct traceeval_iterator *iter, const char *sort_field,
-			    int level, bool ascending);
-int traceeval_iterator_sort_custom(struct traceeval_iterator *iter,
-				   traceeval_cmp_fn sort_fn, void *data);
-int traceeval_iterator_next(struct traceeval_iterator *iter,
-			    const struct traceeval_data **keys);
-int traceeval_iterator_query(struct traceeval_iterator *iter,
-			     const struct traceeval_data **results);
-void traceeval_iterator_results_release(struct traceeval_iterator *iter,
-					const struct traceeval_data *results);
-struct traceeval_stat *traceeval_iterator_stat(struct traceeval_iterator *iter,
-					       struct traceeval_type *type);
-int traceeval_iterator_remove(struct traceeval_iterator *iter);
-
-#endif /* __LIBTRACEEVAL_HIST_H__ */
diff --git a/include/traceeval.h b/include/traceeval.h
index 24415ca..48c28df 100644
--- a/include/traceeval.h
+++ b/include/traceeval.h
@@ -1,120 +1,245 @@ 
 /* SPDX-License-Identifier: MIT */
 /*
- * Copyright (C) 2022 Google Inc, Steven Rostedt <rostedt@goodmis.org>
+ * libtraceeval histogram interface.
+ *
+ * Copyright (C) 2022-2023 Google Inc, Steven Rostedt <rostedt@goodmis.org>
+ * Copyright (C) 2023 Google Inc, Stevie Alvarez <stevie.6strings@gmail.com>
  */
-#ifndef __LIBTRACEEVAL_H__
-#define __LIBTRACEEVAL_H__
+#ifndef __LIBTRACEEVAL_HIST_H__
+#define __LIBTRACEEVAL_HIST_H__
 
 #include <stdlib.h>
+#include <stddef.h>
 #include <stdbool.h>
 
-typedef unsigned long long u64;
-typedef unsigned int u32;
+/* Data definition interfaces */
 
-struct traceeval;
-struct traceeval_key_array;
-struct traceeval_key_info_array;
-struct traceeval_outliers;
+/* Field name/descriptor for number of hits */
+#define TRACEEVAL_VAL_HITS ((const char *)(-1UL))
+
+#define TRACEEVAL_ARRAY_SIZE(data)	(sizeof(data) / sizeof((data)[0]))
 
-enum traceeval_type {
+/* Data type distinguishers */
+enum traceeval_data_type {
 	TRACEEVAL_TYPE_NONE,
-	TRACEEVAL_TYPE_STRING,
-	TRACEEVAL_TYPE_POINTER,
-	TRACEEVAL_TYPE_NUMBER,
-	TRACEEVAL_TYPE_NUMBER_64,
-	TRACEEVAL_TYPE_NUMBER_32,
-	TRACEEVAL_TYPE_NUMBER_16,
 	TRACEEVAL_TYPE_NUMBER_8,
-	TRACEEVAL_TYPE_ARRAY,
-	TRACEEVAL_TYPE_MAX
+	TRACEEVAL_TYPE_NUMBER_16,
+	TRACEEVAL_TYPE_NUMBER_32,
+	TRACEEVAL_TYPE_NUMBER_64,
+	TRACEEVAL_TYPE_NUMBER,
+	TRACEEVAL_TYPE_POINTER,
+	TRACEEVAL_TYPE_STRING,
 };
 
-struct traceeval_key_info {
-	enum traceeval_type	type;
-	size_t			size;
-	ssize_t			count;
-	const char		*name;
+/* Statistics specification flags */
+enum traceeval_flags {
+	TRACEEVAL_FL_KEY		= (1 << 0),
+	TRACEEVAL_FL_VALUE		= (1 << 1),
+	TRACEEVAL_FL_SIGNED		= (1 << 2),
+	TRACEEVAL_FL_TIMESTAMP		= (1 << 3),
+	TRACEEVAL_FL_STAT		= (1 << 4),
 };
 
-struct traceeval_key {
-	enum traceeval_type	type;
-	ssize_t			count;
+/*
+ * Trace data entry for a traceeval histogram
+ * Constitutes keys and values.
+ */
+struct traceeval_data {
+	enum traceeval_data_type		type;
 	union {
-		const char	*string;
-		void   		*pointer;
-		long		number;
-		u64		number_64;
-		u32		number_32;
-		unsigned short	number_16;
-		unsigned char	number_8;
-		void		*array;
+		char				*string;
+		const char			*cstring;
+		void				*pointer;
+		unsigned long			number;
+		unsigned long long		number_64;
+		unsigned int			number_32;
+		unsigned short			number_16;
+		unsigned char			number_8;
 	};
 };
 
-struct traceeval_key_info_array *traceeval_key_info_array_alloc(void);
-void traceeval_key_info_array_free(struct traceeval_key_info_array *iarray);
-int traceeval_key_info_array_add(struct traceeval_key_info_array *iarray,
-					 const struct traceeval_key_info *key);
-
-	struct traceeval *traceeval_n_alloc(const char *name,
-					    const struct traceeval_key_info_array *iarray);
-	void traceeval_free(struct traceeval *teval);
-
-	int traceeval_n_start(struct traceeval *teval, const struct traceeval_key *keys,
-			      unsigned long long start);
-	int traceeval_n_stop(struct traceeval *teval, const struct traceeval_key *keys,
-			     unsigned long long stop);
-	int traceeval_n_continue(struct traceeval *teval, const struct traceeval_key *keys,
-				 unsigned long long start);
-
-	int traceeval_n_set_private(struct traceeval *teval, const struct traceeval_key *keys,
-				    void *data);
-
-	void *traceeval_n_get_private(struct traceeval *teval, const struct traceeval_key *keys);
-
-	struct traceeval_result_array *traceeval_results(struct traceeval *teval);
-
-	size_t traceeval_result_nr(struct traceeval *teval);
-
-	size_t traceeval_key_array_nr(struct traceeval_key_array *karray);
-	const struct traceeval_key *traceeval_key_array_indx(const struct traceeval_key_array *karray,
-							     size_t index);
-	struct traceeval_key_array *traceeval_result_indx_key_array(struct traceeval *teval,
-								    size_t index);
-	ssize_t traceeval_result_indx_cnt(struct traceeval *teval, size_t index);
-	ssize_t traceeval_result_indx_total(struct traceeval *teval, size_t index);
-	ssize_t traceeval_result_indx_max(struct traceeval *teval, size_t index);
-	ssize_t traceeval_result_indx_min(struct traceeval *teval, size_t index);
-
-	ssize_t traceeval_result_keys_cnt(struct traceeval *teval, const struct traceeval_key *keys);
-	ssize_t traceeval_result_keys_total(struct traceeval *teval, const struct traceeval_key *keys);
-	ssize_t traceeval_result_keys_max(struct traceeval *teval, const struct traceeval_key *keys);
-	ssize_t traceeval_result_keys_min(struct traceeval *teval, const struct traceeval_key *keys);
-
-	struct traceeval *traceeval_1_alloc(const char *name, const struct traceeval_key_info info[1]);
-int traceeval_1_start(struct traceeval *teval, struct traceeval_key key,
-		      unsigned long long start);
-int traceeval_1_set_private(struct traceeval *teval, struct traceeval_key key,
-			    void *data);
-void *traceeval_1_get_private(struct traceeval *teval, struct traceeval_key key);
-int traceeval_1_stop(struct traceeval *teval, struct traceeval_key key,
-		     unsigned long long stop);
-int traceeval_1_continue(struct traceeval *teval, struct traceeval_key key,
-			 unsigned long long start);
-
-struct traceeval *traceeval_2_alloc(const char *name, const struct traceeval_key_info kinfo[2]);
-
-int traceeval_sort_totals(struct traceeval *teval, bool ascending);
-int traceeval_sort_max(struct traceeval *teval, bool ascending);
-int traceeval_sort_min(struct traceeval *teval, bool ascending);
-int traceeval_sort_cnt(struct traceeval *teval, bool ascending);
-int traceeval_sort_keys(struct traceeval *teval, bool ascending);
-
-typedef int (*traceeval_cmp_func)(struct traceeval *teval,
-				  const struct traceeval_key_array *A,
-				  const struct traceeval_key_array *B,
-				  void *data);
-
-int traceeval_sort_custom(struct traceeval *teval, traceeval_cmp_func cmp, void *data);
-
-#endif /* __LIBTRACEEVAL_H__ */
+#define __TRACEEVAL_DATA(data_type, member, data)			\
+	{  .type = TRACEEVAL_TYPE_##data_type, .member = (data) }
+
+#define DEFINE_TRACEEVAL_NUMBER(data)	   __TRACEEVAL_DATA(NUMBER, number, data)
+#define DEFINE_TRACEEVAL_NUMBER_8(data)	   __TRACEEVAL_DATA(NUMBER_8, number_8, data)
+#define DEFINE_TRACEEVAL_NUMBER_16(data)   __TRACEEVAL_DATA(NUMBER_16, number_16, data)
+#define DEFINE_TRACEEVAL_NUMBER_32(data)   __TRACEEVAL_DATA(NUMBER_32, number_32, data)
+#define DEFINE_TRACEEVAL_NUMBER_64(data)   __TRACEEVAL_DATA(NUMBER_64, number_64, data)
+#define DEFINE_TRACEEVAL_STRING(data)	   __TRACEEVAL_DATA(STRING, string, data)
+#define DEFINE_TRACEEVAL_CSTRING(data)	   __TRACEEVAL_DATA(STRING, cstring, data)
+#define DEFINE_TRACEEVAL_POINTER(data)	   __TRACEEVAL_DATA(POINTER, pointer, data)
+
+#define __TRACEEVAL_SET(data, data_type, member, val)		\
+	do {							\
+		(data).type = TRACEEVAL_TYPE_##data_type;	\
+		(data).member = (val);				\
+	} while (0)
+
+#define TRACEEVAL_SET_NUMBER(data, val)	     __TRACEEVAL_SET(data, NUMBER, number, val)
+#define TRACEEVAL_SET_NUMBER_8(data, val)    __TRACEEVAL_SET(data, NUMBER_8, number_8, val)
+#define TRACEEVAL_SET_NUMBER_16(data, val)   __TRACEEVAL_SET(data, NUMBER_16, number_16, val)
+#define TRACEEVAL_SET_NUMBER_32(data, val)   __TRACEEVAL_SET(data, NUMBER_32, number_32, val)
+#define TRACEEVAL_SET_NUMBER_64(data, val)   __TRACEEVAL_SET(data, NUMBER_64, number_64, val)
+#define TRACEEVAL_SET_STRING(data, val)	     __TRACEEVAL_SET(data, STRING, string, val)
+#define TRACEEVAL_SET_CSTRING(data, val)     __TRACEEVAL_SET(data, STRING, cstring, val)
+#define TRACEEVAL_SET_POINTER(data, val)     __TRACEEVAL_SET(data, POINTER, pointer, val)
+
+struct traceeval_type;
+struct traceeval;
+
+/* release function callback on traceeval_data */
+typedef void (*traceeval_data_release_fn)(const struct traceeval_type *type,
+					  struct traceeval_data *data);
+
+/* compare function callback to compare traceeval_data */
+typedef int (*traceeval_data_cmp_fn)(struct traceeval *teval,
+				     const struct traceeval_type *type,
+				     const struct traceeval_data *A,
+				     const struct traceeval_data *B);
+
+/* make a unique value */
+typedef int (*traceeval_data_hash_fn)(struct traceeval *teval,
+				      const struct traceeval_type *type,
+				      const struct traceeval_data *data);
+
+typedef int (*traceeval_data_copy_fn)(const struct traceeval_type *type,
+				      struct traceeval_data *dst,
+				      const struct traceeval_data *src);
+
+typedef int (*traceeval_cmp_fn)(struct traceeval *teval,
+				const struct traceeval_data *Akeys,
+				const struct traceeval_data *Avals,
+				const struct traceeval_data *Bkeys,
+				const struct traceeval_data *Bvals,
+				void *data);
+
+/*
+ * struct traceeval_type - Describes the type of a traceevent_data instance
+ * @type: The enum type that describes the traceeval_data
+ * @name: The string name of the traceeval_data
+ * @flags: flags to describe the traceeval_data
+ * @id: User specified identifier
+ * @release: An optional callback for when the data is being released
+ * @cmp: An optional callback to specify a way to compare the type
+ *
+ * The traceeval_type structure defines expectations for a corresponding
+ * traceeval_data instance for a traceeval histogram instance. Used to
+ * describe both keys and values.
+ *
+ * The @id field is an optional value in case the user has multiple struct
+ * traceeval_type instances and needs to distinguish between them into
+ * 'sub-types'.
+ *
+ * For flexibility, @cmp() and @release() take a struct traceeval_type
+ * instance. This allows the user to handle pointer types.
+ * It may also be used for other types if the default cmp() or release()
+ * need to be overridden. Note for string types, even if the release()
+ * is called, the string freeing is still taken care of by the traceeval
+ * infrastructure.
+ *
+ * The @id field is a user specified field that may allow the same callback
+ * to be used by multiple types and not needing to do a strcmp() against the
+ * name (could be used for switch statements).
+ *
+ * @cmp() is used to override the default compare of a type. This is
+ * required to pointer types. It should return 0 on equality, 1 if the first
+ * argument is greater than the second, -1 for the other way around,
+ * and -2 on error.
+ *
+ * @release() is called when a data element is being released (or freed).
+ */
+struct traceeval_type {
+	char				*name;
+	enum traceeval_data_type	type;
+	size_t				flags;
+	size_t				index;
+	size_t				id;
+	traceeval_data_release_fn	release;
+	traceeval_data_cmp_fn		cmp;
+	traceeval_data_copy_fn		copy;
+	traceeval_data_hash_fn		hash;
+};
+
+/* Statistics about a given entry element */
+struct traceeval_stat;
+
+/* Iterator over aggregated data */
+struct traceeval_iterator;
+
+struct traceeval;
+
+/* Histogram interfaces */
+
+#define traceeval_init(keys, vals)					\
+	traceeval_init_size(keys, vals,					\
+			    TRACEEVAL_ARRAY_SIZE(keys),			\
+			    (void *)vals == NULL ?  0 : TRACEEVAL_ARRAY_SIZE(vals))
+
+#define traceeval_init_size(keys, vals, nr_keys, nr_vals)		\
+	traceeval_init_data_size(keys, vals, nr_keys, nr_vals,		\
+				 sizeof(struct traceeval_type),		\
+				 sizeof(struct traceeval_data))
+
+struct traceeval *traceeval_init_data_size(struct traceeval_type *keys,
+					   struct traceeval_type *vals,
+					   size_t nr_keys, size_t nr_vals,
+					   size_t sizeof_type, size_t sizeof_data);
+
+void traceeval_release(struct traceeval *teval);
+
+int traceeval_insert_size(struct traceeval *teval,
+			  const struct traceeval_data *keys, size_t nr_keys,
+			  const struct traceeval_data *vals, size_t nr_vals);
+
+#define traceeval_insert(teval, keys, vals)				\
+	traceeval_insert_size(teval, keys, TRACEEVAL_ARRAY_SIZE(keys), \
+			      vals, (void *)vals == NULL ? 0 : TRACEEVAL_ARRAY_SIZE(vals))
+
+int traceeval_remove_size(struct traceeval *teval,
+			  const struct traceeval_data *keys, size_t nr_keys);
+
+#define traceeval_remove(teval, keys)					\
+	traceeval_remove_size(teval, keys, TRACEEVAL_ARRAY_SIZE(keys))
+
+int traceeval_query_size(struct traceeval *teval, const struct traceeval_data *keys,
+			 size_t nr_keys, const struct traceeval_data **results);
+
+#define traceeval_query(teval, keys, results)				\
+	traceeval_query_size(teval, keys, TRACEEVAL_ARRAY_SIZE(keys), results)
+
+void traceeval_results_release(struct traceeval *teval,
+			       const struct traceeval_data *results);
+
+size_t traceeval_count(struct traceeval *teval);
+
+#define traceeval_stat(teval, keys, type)				\
+	traceeval_stat_size(teval, keys, TRACEEVAL_ARRAY_SIZE(keys), type)
+
+struct traceeval_stat *traceeval_stat_size(struct traceeval *teval,
+					   const struct traceeval_data *keys,
+					   size_t nr_keys,
+					   struct traceeval_type *type);
+
+unsigned long long traceeval_stat_max(struct traceeval_stat *stat);
+unsigned long long traceeval_stat_min(struct traceeval_stat *stat);
+unsigned long long traceeval_stat_total(struct traceeval_stat *stat);
+unsigned long long traceeval_stat_count(struct traceeval_stat *stat);
+
+struct traceeval_iterator *traceeval_iterator_get(struct traceeval *teval);
+void traceeval_iterator_put(struct traceeval_iterator *iter);
+int traceeval_iterator_sort(struct traceeval_iterator *iter, const char *sort_field,
+			    int level, bool ascending);
+int traceeval_iterator_sort_custom(struct traceeval_iterator *iter,
+				   traceeval_cmp_fn sort_fn, void *data);
+int traceeval_iterator_next(struct traceeval_iterator *iter,
+			    const struct traceeval_data **keys);
+int traceeval_iterator_query(struct traceeval_iterator *iter,
+			     const struct traceeval_data **results);
+void traceeval_iterator_results_release(struct traceeval_iterator *iter,
+					const struct traceeval_data *results);
+struct traceeval_stat *traceeval_iterator_stat(struct traceeval_iterator *iter,
+					       struct traceeval_type *type);
+int traceeval_iterator_remove(struct traceeval_iterator *iter);
+
+#endif /* __LIBTRACEEVAL_HIST_H__ */
diff --git a/src/trace-analysis.c b/src/trace-analysis.c
deleted file mode 100644
index ba4e1c7..0000000
--- a/src/trace-analysis.c
+++ /dev/null
@@ -1,805 +0,0 @@ 
-// SPDX-License-Identifier: MIT
-/*
- * Copyright (C) 2022 Google Inc, Steven Rostedt <rostedt@goodmis.org>
- */
-#include <string.h>
-#include <errno.h>
-#include <traceeval.h>
-
-#define HASH_BITS 10
-#define HASH_SIZE (1 << HASH_BITS)
-#define HASH_MASK (HASH_SIZE - 1)
-
-enum sort_type {
-	NONE,
-	KEYS,
-	TOTALS,
-	MAX,
-	MIN,
-	CNT,
-};
-
-struct traceeval_key_info_array {
-	size_t				nr_keys;
-	struct traceeval_key_info	*keys;
-};
-
-struct eval_instance {
-	unsigned long long	total;
-	unsigned long long	last;
-	unsigned long long	max;
-	unsigned long long	min;
-	unsigned long long	cnt;
-	size_t			nr_keys;
-	struct traceeval_key	*keys;
-	void			*private;
-};
-
-struct eval_hash {
-	struct eval_hash		*next;
-	struct eval_instance		eval;
-};
-
-struct traceeval {
-	struct traceeval_key_info_array		array;
-	struct eval_instance			*evals;
-	struct eval_hash			*eval_hash[HASH_SIZE];
-	size_t					nr_evals;
-	struct eval_instance			*results;
-	enum sort_type				sort_type;
-};
-
-struct traceeval_result_array {
-	int				nr_results;
-	struct traceeval_result		*results;
-};
-
-struct traceeval_key_info_array *traceeval_key_info_array_alloc(void)
-{
-	struct traceeval_key_info_array *tarray;
-
-	tarray = calloc(1, sizeof(*tarray));
-	return tarray;
-}
-
-void traceeval_key_info_array_free(struct traceeval_key_info_array *tarray)
-{
-	if (!tarray)
-		return;
-
-	free(tarray->keys);
-	free(tarray);
-}
-
-int traceeval_key_info_array_add(struct traceeval_key_info_array *tarray,
-				 const struct traceeval_key_info *key)
-{
-	size_t nr = tarray->nr_keys;
-	struct traceeval_key_info *kinfo;
-
-	kinfo = realloc(tarray->keys, sizeof(*kinfo) * (nr + 1));
-	if (!kinfo)
-		return -1;
-
-	tarray->keys = kinfo;
-	tarray->nr_keys++;
-	tarray->keys[nr] = *key;
-
-	return 0;
-}
-
-struct traceeval *
-traceeval_n_alloc(const char *name, const struct traceeval_key_info_array *keys)
-{
-	struct traceeval *teval;
-	int i;
-
-	teval = calloc(1, sizeof(*teval));
-	if (!teval)
-		return NULL;
-
-	teval->array.keys = calloc(keys->nr_keys, sizeof(*keys->keys));
-	if (!teval->array.keys)
-		goto fail;
-
-	teval->array.nr_keys = keys->nr_keys;
-
-	for (i = 0; i < keys->nr_keys; i++)
-		teval->array.keys[i] = keys->keys[i];
-
-	return teval;
- fail:
-	free(teval);
-	return NULL;
-}
-
-void traceeval_free(struct traceeval *teval)
-{
-	struct eval_hash *ehash;
-	int i;
-	if (!teval)
-		return;
-
-	for (i = 0; i < HASH_SIZE; i++) {
-		for (ehash = teval->eval_hash[i]; ehash; ) {
-			struct eval_hash *tmp = ehash;
-			ehash = ehash->next;
-			free(tmp);
-		}
-	}
-
-	free(teval->array.keys);
-	free(teval->evals);
-	free(teval);
-}
-
-static int cmp_keys(struct traceeval_key_info_array *tarray,
-		    const struct traceeval_key *A, const struct traceeval_key *B,
-		    int *err)
-{
-	const struct traceeval_key_info *kinfo;
-	unsigned long long A_val, B_val;
-	int ret;
-	int i;
-
-	for (i = 0; i < tarray->nr_keys; i++) {
-		kinfo = &tarray->keys[i];
-
-		/* TBD arrays */
-		if (kinfo->count) {
-			*err = 1;
-			return -1;
-		}
-
-		if (A[i].type != kinfo->type ||
-		    B[i].type != kinfo->type) {
-			*err = 1;
-			return -1;
-		}
-
-		switch (kinfo->type) {
-		case TRACEEVAL_TYPE_STRING:
-			ret = strcmp(A[i].string, B[i].string);
-			if (ret)
-				return ret;
-			continue;
-
-		case TRACEEVAL_TYPE_NUMBER:
-			A_val = A[i].number;
-			B_val = B[i].number;
-			break;
-		case TRACEEVAL_TYPE_NUMBER_64:
-			A_val = A[i].number_64;
-			B_val = B[i].number_64;
-			break;
-		case TRACEEVAL_TYPE_NUMBER_32:
-			A_val = A[i].number_32;
-			B_val = B[i].number_32;
-			break;
-		case TRACEEVAL_TYPE_NUMBER_16:
-			A_val = A[i].number_16;
-			B_val = B[i].number_16;
-			break;
-		case TRACEEVAL_TYPE_NUMBER_8:
-			A_val = A[i].number_8;
-			B_val = B[i].number_8;
-			break;
-		case TRACEEVAL_TYPE_ARRAY:
-		default:
-			*err = 1;
-			return -1;
-		}
-		if (A_val > B_val)
-			return 1;
-		if (A_val < B_val)
-			return -1;
-	}
-	return 0;
-}
-
-static int make_key(struct traceeval *teval, const struct traceeval_key *keys, int *err)
-{
-	struct traceeval_key_info *kinfo;
-	bool calc;
-	int len, l;
-	int ret = 0;
-	int i;
-
-	for (i = 0; i < teval->array.nr_keys; i++) {
-		kinfo = &teval->array.keys[i];
-
-		/* TBD arrays */
-		if (kinfo->count) {
-			*err = 1;
-			return -1;
-		}
-
-		if (keys[i].type != kinfo->type) {
-			*err = 1;
-			return -1;
-		}
-
-		calc = false;
-
-		switch (kinfo->type) {
-		case TRACEEVAL_TYPE_STRING:
-			len = strlen(keys[i].string);
-
-			for (l = 0; l < len; l++) {
-				unsigned int c = keys[i].string[l];
-
-				ret += c << ((l & 3) * 8);
-			}
-
-			continue;
-
-		case TRACEEVAL_TYPE_NUMBER_32:
-			calc = true;
-			/* fall though */
-		case TRACEEVAL_TYPE_NUMBER:
-			if (calc || sizeof(keys[i].number) == 4) {
-				ret += keys[i].number;
-				continue;
-			}
-			/* fall through */
-		case TRACEEVAL_TYPE_NUMBER_64:
-			ret += keys[i].number_64 >> 32;
-			ret += keys[i].number_64 & ((1ULL << 32) - 1);
-			break;
-			break;
-		case TRACEEVAL_TYPE_NUMBER_16:
-			ret += keys[i].number_16;
-			break;
-		case TRACEEVAL_TYPE_NUMBER_8:
-			ret += keys[i].number_8;
-			break;
-		case TRACEEVAL_TYPE_ARRAY:
-		default:
-			*err = 1;
-			return -1;
-		}
-	}
-	return ret & HASH_MASK;
-}
-
-static struct eval_hash *find_eval(struct traceeval *teval, const struct traceeval_key *keys,
-				   int *err, int *pkey)
-{
-	struct eval_hash *ehash;
-	int key = make_key(teval, keys, err);
-
-	if (key < 0)
-		return NULL;
-
-	if (pkey)
-		*pkey = key;
-
-	for (ehash = teval->eval_hash[key]; ehash; ehash = ehash->next) {
-		if (cmp_keys(&teval->array, keys, ehash->eval.keys, err) == 0)
-			return ehash;
-	}
-	return NULL;
-}
-
-static struct eval_hash *
-insert_eval(struct traceeval *teval, const struct traceeval_key *keys, int key)
-{
-	struct eval_instance *eval;
-	struct eval_hash *ehash;
-	int i;
-
-	ehash = calloc(1, sizeof(*ehash));
-	if (!ehash)
-		return NULL;
-
-	eval = &ehash->eval;
-
-	eval->keys = calloc(teval->array.nr_keys, sizeof(*eval->keys));
-	if (!eval->keys)
-		return NULL;
-	for (i = 0; i < teval->array.nr_keys; i++)
-		eval->keys[i] = keys[i];
-	eval->nr_keys = teval->array.nr_keys;
-	teval->nr_evals++;
-
-	ehash->next = teval->eval_hash[key];
-	teval->eval_hash[key] = ehash;
-
-	return ehash;
-}
-
-static struct eval_instance *
-get_eval_instance(struct traceeval *teval, const struct traceeval_key *keys)
-{
-	struct eval_hash *ehash;
-	int err = 0;
-	int key = -1;
-
-	ehash = find_eval(teval, keys, &err, &key);
-	if (!ehash) {
-		ehash = insert_eval(teval, keys, key);
-		if (!ehash)
-			return NULL;
-	}
-	return &ehash->eval;
-}
-
-int traceeval_n_start(struct traceeval *teval, const struct traceeval_key *keys,
-		      unsigned long long start)
-{
-	struct eval_instance *eval;
-
-	eval = get_eval_instance(teval, keys);
-	if (!eval)
-		return -1;
-
-	eval->last = start;
-	return 0;
-}
-
-int traceeval_n_continue(struct traceeval *teval, const struct traceeval_key *keys,
-			 unsigned long long start)
-{
-	struct eval_instance *eval;
-
-	eval = get_eval_instance(teval, keys);
-	if (!eval)
-		return -1;
-
-	if (eval->last)
-		return 0;
-
-	eval->last = start;
-	return 0;
-}
-
-int traceeval_n_set_private(struct traceeval *teval, const struct traceeval_key *keys,
-			    void *data)
-{
-	struct eval_instance *eval;
-
-	/* Setting an instance forces a creation of it */
-	eval = get_eval_instance(teval, keys);
-	if (!eval)
-		return -1;
-
-	eval->private = data;
-	return 0;
-}
-
-void *traceeval_n_get_private(struct traceeval *teval, const struct traceeval_key *keys)
-{
-	struct eval_hash *ehash;
-	int err = 0;
-
-	ehash = find_eval(teval, keys, &err, NULL);
-	if (!ehash)
-		return NULL;
-	return ehash->eval.private;
-}
-
-int traceeval_n_stop(struct traceeval *teval, const struct traceeval_key *keys,
-		     unsigned long long stop)
-{
-	struct eval_instance *eval;
-	unsigned long long delta;
-
-	eval = get_eval_instance(teval, keys);
-	if (!eval)
-		return -1;
-
-	if (!eval->last)
-		return 1;
-
-	delta = stop - eval->last;
-	eval->total += delta;
-	if (!eval->min || eval->min > delta)
-		eval->min = delta;
-	if (eval->max < delta)
-		eval->max = delta;
-	eval->cnt++;
-
-	eval->last = 0;
-
-	return 0;
-}
-
-size_t traceeval_result_nr(struct traceeval *teval)
-{
-	return teval->nr_evals;
-}
-
-size_t traceeval_key_array_nr(struct traceeval_key_array *karray)
-{
-	struct eval_instance *eval = (struct eval_instance *)karray;
-
-	if (!karray)
-		return 0;
-
-	return eval->nr_keys;
-}
-
-const struct traceeval_key *
-traceeval_key_array_indx(const struct traceeval_key_array *karray, size_t index)
-{
-	struct eval_instance *eval = (struct eval_instance *)karray;
-
-	if (!karray || index >= eval->nr_keys)
-		return NULL;
-
-	return &eval->keys[index];
-}
-
-static int create_results(struct traceeval *teval)
-{
-	struct eval_hash *ehash;
-	int r = 0;
-	int i;
-
-	if (teval->results)
-		return 0;
-
-	teval->results = calloc(teval->nr_evals, sizeof(*teval->results));
-	if (!teval->results)
-		return -1;
-
-	for (i = 0; i < HASH_SIZE; i++) {
-		for (ehash = teval->eval_hash[i]; ehash; ehash = ehash->next) {
-			teval->results[r++] = ehash->eval;
-		}
-	}
-	return 0;
-}
-
-static int eval_sort(struct traceeval *teval, enum sort_type sort_type, bool ascending);
-
-static struct eval_instance *get_result(struct traceeval *teval, size_t index)
-{
-	if (index >= teval->nr_evals)
-		return NULL;
-
-	if (!teval->results) {
-		create_results(teval);
-		if (!teval->results)
-			return NULL;
-		eval_sort(teval, KEYS, true);
-	}
-
-	if (teval->results)
-		return &teval->results[index];
-
-	return &teval->evals[index];
-}
-
-struct traceeval_key_array *
-traceeval_result_indx_key_array(struct traceeval *teval, size_t index)
-{
-	struct eval_instance *eval = get_result(teval, index);
-
-	if (!eval)
-		return NULL;
-
-	return (struct traceeval_key_array *)eval;
-}
-
-ssize_t
-traceeval_result_indx_cnt(struct traceeval *teval, size_t index)
-{
-	struct eval_instance *eval = get_result(teval, index);
-
-	if (!eval)
-		return -1;
-
-	return eval->cnt;
-}
-
-ssize_t
-traceeval_result_indx_total(struct traceeval *teval, size_t index)
-{
-	struct eval_instance *eval = get_result(teval, index);
-
-	if (!eval)
-		return -1;
-
-	return eval->total;
-}
-
-ssize_t
-traceeval_result_indx_max(struct traceeval *teval, size_t index)
-{
-	struct eval_instance *eval = get_result(teval, index);
-
-	if (!eval)
-		return -1;
-
-	return eval->max;
-}
-
-ssize_t
-traceeval_result_indx_min(struct traceeval *teval, size_t index)
-{
-	struct eval_instance *eval = get_result(teval, index);
-
-	if (!eval)
-		return -1;
-
-	return eval->min;
-}
-
-
-ssize_t
-traceeval_result_keys_cnt(struct traceeval *teval, const struct traceeval_key *keys)
-{
-	struct eval_hash *ehash;
-	int err = 0;
-
-	ehash = find_eval(teval, keys, &err, NULL);
-	if (!ehash)
-		return -1;
-	return ehash->eval.cnt;
-}
-
-ssize_t
-traceeval_result_keys_total(struct traceeval *teval, const struct traceeval_key *keys)
-{
-	struct eval_hash *ehash;
-	int err = 0;
-
-	ehash = find_eval(teval, keys, &err, NULL);
-	if (!ehash)
-		return -1;
-	return ehash->eval.total;
-}
-
-ssize_t
-traceeval_result_keys_max(struct traceeval *teval, const struct traceeval_key *keys)
-{
-	struct eval_hash *ehash;
-	int err = 0;
-
-	ehash = find_eval(teval, keys, &err, NULL);
-	if (!ehash)
-		return -1;
-	return ehash->eval.max;
-}
-
-ssize_t
-traceeval_result_keys_min(struct traceeval *teval, const struct traceeval_key *keys)
-{
-	struct eval_hash *ehash;
-	int err = 0;
-
-	ehash = find_eval(teval, keys, &err, NULL);
-	if (!ehash)
-		return -1;
-	return ehash->eval.min;
-}
-
-struct traceeval *
-traceeval_1_alloc(const char *name, const struct traceeval_key_info kinfo[1])
-{
-	struct traceeval_key_info key[1] = { kinfo[0] };
-	struct traceeval_key_info_array karray = {
-		.nr_keys = 1,
-		.keys = key,
-	};
-
-	return traceeval_n_alloc(name, &karray);
-}
-
-int traceeval_1_start(struct traceeval *teval, struct traceeval_key key,
-		      unsigned long long start)
-{
-	struct traceeval_key keys[1] = { key };
-
-	return traceeval_n_start(teval, keys, start);
-}
-
-int traceeval_1_continue(struct traceeval *teval, struct traceeval_key key,
-			 unsigned long long start)
-{
-	struct traceeval_key keys[1] = { key };
-
-	return traceeval_n_continue(teval, keys, start);
-}
-
-int traceeval_1_set_private(struct traceeval *teval, struct traceeval_key key,
-			    void *data)
-{
-	struct traceeval_key keys[1] = { key };
-
-	return traceeval_n_set_private(teval, keys, data);
-}
-
-void *traceeval_1_get_private(struct traceeval *teval, struct traceeval_key key)
-{
-	struct traceeval_key keys[1] = { key };
-
-	return traceeval_n_get_private(teval, keys);
-}
-
-int traceeval_1_stop(struct traceeval *teval, struct traceeval_key key,
-		     unsigned long long stop)
-{
-	struct traceeval_key keys[1] = { key };
-
-	return traceeval_n_stop(teval, keys, stop);
-}
-
-struct traceeval *
-traceeval_2_alloc(const char *name, const struct traceeval_key_info kinfo[2])
-{
-	struct traceeval_key_info key[2] = { kinfo[0], kinfo[1] };
-	struct traceeval_key_info_array karray = {
-		.nr_keys = 2,
-		.keys = key,
-	};
-
-	return traceeval_n_alloc(name, &karray);
-}
-
-static int cmp_totals(const void *A, const void *B)
-{
-	const struct eval_instance *a = A;
-	const struct eval_instance *b = B;
-
-	if (a->total < b->total)
-		return -1;
-	return a->total > b->total;
-}
-
-static int cmp_max(const void *A, const void *B)
-{
-	const struct eval_instance *a = A;
-	const struct eval_instance *b = B;
-
-	if (a->max < b->max)
-		return -1;
-	return a->max > b->max;
-}
-
-static int cmp_min(const void *A, const void *B)
-{
-	const struct eval_instance *a = A;
-	const struct eval_instance *b = B;
-
-	if (a->min < b->min)
-		return -1;
-	return a->min > b->min;
-}
-
-static int cmp_cnt(const void *A, const void *B)
-{
-	const struct eval_instance *a = A;
-	const struct eval_instance *b = B;
-
-	if (a->cnt < b->cnt)
-		return -1;
-	return a->cnt > b->cnt;
-}
-
-static int cmp_inverse(const void *A, const void *B, void *cmp)
-{
-	int (*cmp_func)(const void *, const void *) = cmp;
-
-	return cmp_func(B, A);
-}
-
-static int cmp_evals(const void *A, const void *B, void *data)
-{
-	const struct eval_instance *a = A;
-	const struct eval_instance *b = B;
-	struct traceeval *teval = data;
-	int err;
-
-	return cmp_keys(&teval->array, a->keys, b->keys, &err);
-}
-
-static int cmp_evals_dec(const void *A, const void *B, void *data)
-{
-	struct traceeval *teval = data;
-	int err;
-
-	return cmp_keys(&teval->array, B, A, &err);
-}
-
-static int eval_sort(struct traceeval *teval, enum sort_type sort_type, bool ascending)
-{
-	int (*cmp_func)(const void *, const void *);
-
-	if (create_results(teval) < 0)
-		return -1;
-
-	if (teval->sort_type == sort_type)
-		return 0;
-
-	switch (sort_type) {
-	case TOTALS:
-		cmp_func = cmp_totals;
-		break;
-	case MAX:
-		cmp_func = cmp_max;
-		break;
-	case MIN:
-		cmp_func = cmp_min;
-		break;
-	case CNT:
-		cmp_func = cmp_cnt;
-		break;
-	case NONE:
-	case KEYS:
-		if (ascending) {
-			qsort_r(teval->results, teval->nr_evals,
-				sizeof(*teval->results), cmp_evals, teval);
-		} else {
-			qsort_r(teval->results, teval->nr_evals,
-				sizeof(*teval->results), cmp_evals_dec, teval);
-		}
-		return 0;
-	}
-
-	if (ascending)
-		qsort(teval->results, teval->nr_evals, sizeof(*teval->results), cmp_func);
-	else
-		qsort_r(teval->results, teval->nr_evals, sizeof(*teval->results),
-			cmp_inverse, cmp_func);
-	teval->sort_type = sort_type;
-	return 0;
-}
-
-int traceeval_sort_totals(struct traceeval *teval, bool ascending)
-{
-	return eval_sort(teval, TOTALS, ascending);
-}
-
-int traceeval_sort_max(struct traceeval *teval, bool ascending)
-{
-	return eval_sort(teval, MAX, ascending);
-}
-
-int traceeval_sort_min(struct traceeval *teval, bool ascending)
-{
-	return eval_sort(teval, MIN, ascending);
-}
-
-int traceeval_sort_cnt(struct traceeval *teval, bool ascending)
-{
-	return eval_sort(teval, CNT, ascending);
-}
-
-struct cmp_data {
-	struct traceeval	*teval;
-	traceeval_cmp_func	func;
-	void			*data;
-};
-
-static int cmp_custom(const void *A, const void *B, void *data)
-{
-	const struct traceeval_key_array *a = A;
-	const struct traceeval_key_array *b = B;
-	struct cmp_data *cdata = data;
-
-	return cdata->func(cdata->teval, a, b, cdata->data);
-}
-
-int traceeval_sort_custom(struct traceeval *teval, traceeval_cmp_func cmp, void *data)
-{
-	struct cmp_data cdata;
-
-	if (create_results(teval) < 0)
-		return -1;
-
-	cdata.teval = teval;
-	cdata.func = cmp;
-	cdata.data = data;
-
-	qsort_r(teval->results, teval->nr_evals,
-		sizeof(*teval->results), cmp_custom, &cdata);
-
-	return 0;
-}
-
-int traceeval_sort_keys(struct traceeval *teval, bool ascending)
-{
-	return eval_sort(teval, KEYS, ascending);
-}