RCU Judy Array (rcuja) implementation
[userspace-rcu.git] / tests / utils / rcuja-testpop.c
CommitLineData
db61f215
MD
1/*
2 * rcuja/testpop.c
3 *
4 * Userspace RCU library - RCU Judy Array population size test
5 *
6 * Copyright 2012-2013 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23/*
24 * This program generates random populations, and shows the largest
25 * sub-class generated, as well as the distribution of sub-class size
26 * for the largest sub-class of each population.
27 */
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <stdint.h>
32#include <time.h>
33#include <string.h>
34#include <limits.h>
35#include <assert.h>
36
37static int sel_pool_len = 50; /* default */
38static int nr_distrib = 2; /* default */
39//#define SEL_POOL_LEN 100
40//#define NR_POOLS 10000000ULL
41
42static uint8_t pool[256];
43static uint8_t nr_one[8];
44static uint8_t nr_2d_11[8][8];
45static uint8_t nr_2d_10[8][8];
46static uint8_t nr_2d_01[8][8];
47static uint8_t nr_2d_00[8][8];
48static int global_max_minsubclass_len = 0;
49
50static unsigned int subclass_len_distrib[256];
51
52static int verbose;
53
54static
55uint8_t random_char(void)
56{
57 return (uint8_t) random();
58}
59
60static
61void print_pool(void)
62{
63 int i;
64
65 printf("pool: ");
66 for (i = 0; i < sel_pool_len; i++) {
67 printf("%d ", (int) pool[i]);
68 }
69 printf("\n");
70}
71
72static
73void gen_pool(void)
74{
75 uint8_t src_pool[256];
76 int i;
77 int nr_left = 256;
78
79 memset(pool, 0, sizeof(pool));
80 for (i = 0; i < 256; i++)
81 src_pool[i] = (uint8_t) i;
82 for (i = 0; i < sel_pool_len; i++) {
83 int sel;
84
85 sel = random_char() % nr_left;
86 pool[i] = src_pool[sel];
87 src_pool[sel] = src_pool[nr_left - 1];
88 nr_left--;
89 }
90}
91
92static
93void count_pool(void)
94{
95 int i;
96
97 memset(nr_one, 0, sizeof(nr_one));
98 memset(nr_2d_11, 0, sizeof(nr_2d_11));
99 memset(nr_2d_10, 0, sizeof(nr_2d_10));
100 memset(nr_2d_01, 0, sizeof(nr_2d_01));
101 memset(nr_2d_00, 0, sizeof(nr_2d_00));
102
103 for (i = 0; i < sel_pool_len; i++) {
104 if (nr_distrib == 2) {
105 int j;
106
107 for (j = 0; j < 8; j++) {
108 if (pool[i] & (1U << j))
109 nr_one[j]++;
110 }
111 }
112
113 if (nr_distrib == 4) {
114 int bit_i, bit_j;
115
116 for (bit_i = 0; bit_i < 8; bit_i++) {
117 for (bit_j = 0; bit_j < bit_i; bit_j++) {
118 if (pool[i] & (1U << bit_i)) {
119 if (pool[i] & (1U << bit_j)) {
120 nr_2d_11[bit_i][bit_j]++;
121 } else {
122 nr_2d_10[bit_i][bit_j]++;
123 }
124 } else {
125 if (pool[i] & (1U << bit_j)) {
126 nr_2d_01[bit_i][bit_j]++;
127 } else {
128 nr_2d_00[bit_i][bit_j]++;
129 }
130 }
131 }
132 }
133 }
134 }
135}
136
137static
138void print_count(void)
139{
140 int i;
141
142 printf("pool distribution:\n");
143
144 if (nr_distrib == 2) {
145 printf(" 0 1\n");
146 printf("----------\n");
147 for (i = 0; i < 8; i++) {
148 printf("%3d %3d\n",
149 sel_pool_len - nr_one[i], nr_one[i]);
150 }
151 }
152
153 if (nr_distrib == 4) {
154 /* TODO */
155 }
156 printf("\n");
157}
158
159static
160void stat_count_1d(void)
161{
162 unsigned int overall_best_distance = UINT_MAX;
163 unsigned int overall_minsubclass_len;
164 int i;
165
166 for (i = 0; i < 8; i++) {
167 int distance_to_best;
168
169 distance_to_best = ((unsigned int) nr_one[i] << 1U) - sel_pool_len;
170 if (distance_to_best < 0)
171 distance_to_best = -distance_to_best;
172 if (distance_to_best < overall_best_distance) {
173 overall_best_distance = distance_to_best;
174 }
175 }
176 overall_minsubclass_len = (overall_best_distance + sel_pool_len) >> 1UL;
177 if (overall_minsubclass_len > global_max_minsubclass_len) {
178 global_max_minsubclass_len = overall_minsubclass_len;
179 }
180 subclass_len_distrib[overall_minsubclass_len]++;
181}
182
183static
184void stat_count_2d(void)
185{
186 int overall_best_distance = INT_MAX;
187 unsigned int overall_minsubclass_len = 0;
188 int bit_i, bit_j;
189
190 for (bit_i = 0; bit_i < 8; bit_i++) {
191 for (bit_j = 0; bit_j < bit_i; bit_j++) {
192 int distance_to_best[4], subclass_len[4];
193
194 distance_to_best[0] = ((unsigned int) nr_2d_11[bit_i][bit_j] << 2U) - sel_pool_len;
195 distance_to_best[1] = ((unsigned int) nr_2d_10[bit_i][bit_j] << 2U) - sel_pool_len;
196 distance_to_best[2] = ((unsigned int) nr_2d_01[bit_i][bit_j] << 2U) - sel_pool_len;
197 distance_to_best[3] = ((unsigned int) nr_2d_00[bit_i][bit_j] << 2U) - sel_pool_len;
198
199 subclass_len[0] = nr_2d_11[bit_i][bit_j];
200 subclass_len[1] = nr_2d_10[bit_i][bit_j];
201 subclass_len[2] = nr_2d_01[bit_i][bit_j];
202 subclass_len[3] = nr_2d_00[bit_i][bit_j];
203
204 /* Consider worse distance above best */
205 if (distance_to_best[1] > 0 && distance_to_best[1] > distance_to_best[0]) {
206 distance_to_best[0] = distance_to_best[1];
207 subclass_len[0] = subclass_len[1];
208 }
209 if (distance_to_best[2] > 0 && distance_to_best[2] > distance_to_best[0]) {
210 distance_to_best[0] = distance_to_best[2];
211 subclass_len[0] = subclass_len[2];
212 }
213 if (distance_to_best[3] > 0 && distance_to_best[3] > distance_to_best[0]) {
214 distance_to_best[0] = distance_to_best[3];
215 subclass_len[0] = subclass_len[3];
216 }
217
218 /*
219 * If our worse distance is better than overall,
220 * we become new best candidate.
221 */
222 if (distance_to_best[0] < overall_best_distance) {
223 overall_best_distance = distance_to_best[0];
224 overall_minsubclass_len = subclass_len[0];
225 }
226 }
227 }
228 if (overall_minsubclass_len > global_max_minsubclass_len) {
229 global_max_minsubclass_len = overall_minsubclass_len;
230 }
231 subclass_len_distrib[overall_minsubclass_len]++;
232}
233
234static
235void stat_count(void)
236{
237 switch (nr_distrib) {
238 case 2:
239 stat_count_1d();
240 break;
241 case 4:
242 stat_count_2d();
243 break;
244 default:
245 assert(0);
246 break;
247 }
248}
249
250static
251void print_distrib(void)
252{
253 int i;
254 unsigned long long tot = 0;
255
256 for (i = 0; i < 256; i++) {
257 tot += subclass_len_distrib[i];
258 }
259 if (tot == 0)
260 return;
261 printf("Distribution:\n");
262 for (i = 0; i < 256; i++) {
263 if (!subclass_len_distrib[i])
264 continue;
265 printf("(%u, %u, %llu%%) ",
266 i, subclass_len_distrib[i],
267 100 * (unsigned long long) subclass_len_distrib[i] / tot);
268 }
269 printf("\n");
270}
271
272static
273void print_stat(uint64_t i)
274{
275 printf("after %llu pools, global_max_minsubclass_len: %d\n",
276 (unsigned long long) i, global_max_minsubclass_len);
277 print_distrib();
278}
279
280int main(int argc, char **argv)
281{
282 uint64_t i = 0;
283
284 srandom(time(NULL));
285
286 if (argc > 1) {
287 sel_pool_len = atoi(argv[1]);
288 if (sel_pool_len > 256 || sel_pool_len < 1) {
289 printf("Wrong pool len\n");
290 return -1;
291 }
292 }
293 printf("pool len: %d\n", sel_pool_len);
294
295 if (argc > 2) {
296 nr_distrib = atoi(argv[2]);
297 if (nr_distrib > 256 || nr_distrib < 1) {
298 printf("Wrong number of distributions\n");
299 return -1;
300 }
301 }
302
303 if (argc > 3) {
304 if (!strcmp(argv[3], "-v")) {
305 verbose = 1;
306 }
307 }
308
309 printf("pool distributions: %d\n", nr_distrib);
310
311 if (nr_distrib != 2 && nr_distrib != 4) {
312 printf("Wrong number of distributions. Only 2 and 4 supported.\n");
313 return -1;
314 }
315
316 //for (i = 0; i < NR_POOLS; i++) {
317 while (1) {
318 gen_pool();
319 count_pool();
320 if (verbose) {
321 print_pool();
322 print_count();
323 }
324 stat_count();
325 if (!(i % 100000ULL))
326 print_stat(i);
327 i++;
328 }
329 print_stat(i);
330 print_distrib();
331
332 return 0;
333}
This page took 0.03369 seconds and 4 git commands to generate.