blob: 2c4669418bf347af565fbca965085a2e3f6b27ea [file] [log] [blame]
Chris Lattner23028e82003-05-09 03:49:51 +00001/*
2 * LLUBENCHMARK
3 * Craig Zilles (zilles@cs.wisc.edu)
4 * http://www.cs.wisc.edu/~zilles/llubenchmark.html
5 *
6 * This program is a linked list traversal micro-benchmark, which can
7 * be used (among other things) to approximate the non-benchmark
8 * Health.
9 *
10 * The benchmark executes for a proscribed number of iterations (-i),
11 * and on every iteration the lists are traversed and potentially
12 * extended. The number of lists can be specified (-n) as well as the
13 * size of the elements in the list (-s). The initial length of the
14 * lists can be set (-l) as well as the growth rate (-g). The growth
15 * rate must be non-negative, but can be a floating point number, in
16 * which case random numbers are used to determine whether a list is
17 * extended on a particular cycle (all lists are extended
18 * independently). If the -t option is specified, the insertion
19 * occurs at the tail, otherwise at the head. If the -d option is
20 * specified, the elements are dirtied during the traversal (which
21 * will necessitate a write-back when the data is evicted from the
22 * cache).
23 *
24 * To approximate the non-benchmark Health, use the options:
25 * -i <num iterations> -g .333 -d -t -n 341
26 *
27 * (the growth rate of the lists in health is different for different
28 * levels of the hierarchy and the constant .333 is just my
29 * approximation of the growth rate).
30 *
31 */
32
33#include <stdio.h>
34#include <stdlib.h>
35#if 0
36#include <assert.h>
37#else
38#define assert(x)
39#endif
40
41/* This file should compile stand alone */
42
43struct element {
44 struct element *next;
45 int count;
46};
47
48void
49usage(char *name) {
50 printf("%s:\n", name);
51 printf("-i <number of (I)terations>\n");
52 printf("[-l <initial (L)ength of list, in elements>] (default 1)\n");
53 printf("[-n <(N)umber of lists>] (default 1 list)\n");
54 printf("[-s <(S)ize of element>] (default 32 bytes)\n");
55 printf("[-g <(G)rowth rate per list, in elements per iteration>] (default 0)\n");
56 printf("[-d] ((D)irty each element during traversal, default off)\n");
57 printf("[-t] (insert at (T)ail of list, default off)\n");
58}
59
60#define ALLOC_SIZE 127 /* pick wierd num to break strides */
61struct element *free_list = NULL;
62int next_free = ALLOC_SIZE;
63int element_size = 32;
64int num_allocated = 0;
65
66#if 1
67struct element *
68allocate() {
69 if (next_free == ALLOC_SIZE) {
70 next_free = 0;
71 free_list = (struct element *) malloc (ALLOC_SIZE * element_size);
72 assert(free_list != 0);
73 }
74 num_allocated ++;
75 return (struct element *)
76 (((char *)free_list) + ((next_free ++) * element_size));
77}
78#else
79struct element * allocate() {
80 num_allocated ++;
81 return (struct element*)malloc(sizeof(struct element));
82}
83#endif
84
85int
86main(int argc, char *argv[]) {
87 int max_iterations = 1000,
88 dirty = 1,
89 num_lists = 196,
90 tail = 1,
91 initial_length = 1;
92 float growth_rate = 0.333;
93 char c = 0;
94 int i = 0, j = 0, k = 0;
95 int accumulate = 0;
96
97 struct element **lists = NULL;
98 float growth = 0.0;
99
100 int arg = 1;
101
102 printf("This benchmark modified to not use hard coded pool allocation!\n");
103 while (arg < argc) {
104 if ((argv[arg][0] != '-') || (argv[arg][2] != 0)) {
105 printf("parse error in %s\n", argv[arg]);
106 usage(argv[0]);
107 return(-1);
108 }
109 c = argv[arg][1];
110 arg ++;
111 switch(c) {
112 case 'd': dirty = 1; break;
113 case 'g': growth_rate = atof(argv[arg++]); break;
114 case 'i': max_iterations = atoi(argv[arg++]); break;
115 case 'l': initial_length = atoi(argv[arg++]); break;
116 case 'n': num_lists = atoi(argv[arg++]); break;
117 case 's': element_size = atoi(argv[arg++]); break;
118 case 't': tail = 1; break;
119 default:
120 printf("unrecognized option: %c\n", c);
121 usage(argv[0]);
122 return(-1);
123 }
124 }
125
126 assert (element_size > sizeof(struct element));
127 assert (initial_length > 0);
128
129 /* build lists */
130 lists = (struct element **) malloc (num_lists * sizeof(struct element *));
131 assert(lists != 0);
132
133 for (i = 0 ; i < num_lists ; i ++) {
134 lists[i] = NULL;
135 }
136
137
138 for (i = 0 ; i < initial_length ; i ++) {
139 for (j = 0 ; j < num_lists ; j ++) {
140 struct element *e = allocate();
141 e->next = lists[j];
142 lists[j] = e;
143 }
144 }
145
146 /* iterate */
147 for (i = 0 ; i < max_iterations ; i ++) {
148 if ((i % 10) == 0) {
149 printf("%d\n", i);
150 }
151 /* traverse lists */
152 for (j = 0 ; j < num_lists ; j ++) {
153 struct element *trav = lists[j];
154 while (trav != NULL) {
155 accumulate += trav->count;
156 if (dirty) {
157 trav->count ++;
158 }
159 trav = trav->next;
160 }
161 }
162
163 /* grow lists */
164 growth += growth_rate;
165 j = growth;
166 growth -= j;
167 for ( ; j > 0 ; j --) {
168 for (k = 0 ; k < num_lists ; k ++) {
169 struct element *e = allocate();
170 if (tail) {
171 struct element *trav = lists[k];
172 while (trav->next != NULL) {
173 trav = trav->next;
174 }
175 trav->next = e;
176 e->next = NULL;
177 } else {
178 e->next = lists[k];
179 lists[k] = e;
180 }
181 }
182 }
183 }
184 printf ("num allocated %d\n", num_allocated);
185 return 0;
186}
187