summaryrefslogtreecommitdiff
path: root/lib/libc_r/BENCH/bench.h
blob: 1d68915a75ee665cff52bea1f1155fe22f314397 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

#define BENCH_LOOPS	(16384)
#include <sys/time.h>

typedef struct  {
	int i;
	int n;
	int divisor;
	struct timespec start;
	struct timespec end;
	struct timespec elapsed;
	double average;
	char *name;
	char *doc;
	char *units;
} bench_t;

#define bench_now(tsp) \
	clock_gettime(CLOCK_REALTIME, (tsp))

/*
 * Repeat the body of the loop 'max' times, with a few extra 'warm up'
 * cycles to negate cache effects.
 */
#define bench_amortize(b, max) 						\
	for ((b)->i = -64,						\
	     (b)->n = (max);						\
	     (b)->i < (b)->n;						\
	     (b)->i ++,							\
	     ((b)->i == 0 ? bench_now(&(b)->start) :			\
	      ((b)->i == (b)->n ? bench_now(&(b)->end)			\
		:0))\
	)

#define bench_init(b, nm, dc, un) do {					\
	(b)->name = (nm);						\
	(b)->doc = (dc);						\
	(b)->units = (un);						\
	timespecclear(&(b)->start);					\
	timespecclear(&(b)->end);					\
	timespecclear(&(b)->elapsed);					\
	(b)->n = (b)->i = 0;						\
	(b)->divisor = 1;						\
} while (0)
	
#define bench_header(b)							\
	printf("----------------------------------------------------\n" \
	       "Name:\t%s\nDesc:%s\n",	(b)->name, (b)->doc)

#define bench_report(b) do {						\
	struct timespec elapsed;					\
	bench_t overhead;						\
									\
	/* compute the loop overhead */					\
	bench_amortize(&overhead, BENCH_LOOPS) { /* nothing */ }	\
									\
	timespecsub(&(b)->end, &(b)->start, &(b)->elapsed);		\
	(b)->average = ((double)(b)->elapsed.tv_sec * 1000000000.0 +	\
	    (b)->elapsed.tv_nsec) / (double)((b)->divisor) / 		\
	    (double)((b)->n);						\
									\
	printf("Time: %f usec %s\n", (b)->average, (b)->units);		\
	if ((b)->divisor != 1)						\
		printf("\t(%d operations per cycle)\n", (b)->divisor);	\
} while (0)