blob: e9f4251a7b1ae699128cb6531effceb5844c5bad [file] [log] [blame]
Dave Barach8e8f98c2017-02-03 11:58:53 -05001#include <vppinfra/time.h>
2#include <vppinfra/cache.h>
3#include <vppinfra/error.h>
4#include <vppinfra/tw_timer_2t_1w_2048sl.h>
Dave Barach90767892020-04-01 14:34:39 -04005#include <vppinfra/tw_timer_2t_2w_512sl.h>
Dave Barach8e8f98c2017-02-03 11:58:53 -05006#include <vppinfra/tw_timer_16t_2w_512sl.h>
Dave Barach4af9ba12017-06-07 15:18:23 -04007#include <vppinfra/tw_timer_4t_3w_256sl.h>
8#include <vppinfra/tw_timer_1t_3w_1024sl_ov.h>
Dave Barach8e8f98c2017-02-03 11:58:53 -05009
10typedef struct
11{
12 /** Handle returned from tw_start_timer */
13 u32 stop_timer_handle;
14
15 /** Test item should expire at this clock tick */
Dave Barach4af9ba12017-06-07 15:18:23 -040016 u64 expected_to_expire;
Dave Barach8e8f98c2017-02-03 11:58:53 -050017} tw_timer_test_elt_t;
18
19typedef struct
20{
21 /** Pool of test objects */
22 tw_timer_test_elt_t *test_elts;
23
24 /** The single-wheel */
25 tw_timer_wheel_2t_1w_2048sl_t single_wheel;
26
27 /** The double-wheel */
28 tw_timer_wheel_16t_2w_512sl_t double_wheel;
29
Dave Barach4af9ba12017-06-07 15:18:23 -040030 /* The triple wheel */
31 tw_timer_wheel_4t_3w_256sl_t triple_wheel;
32
33 /* The triple wheel with overflow vector */
34 tw_timer_wheel_1t_3w_1024sl_ov_t triple_ov_wheel;
35
Dave Barach90767892020-04-01 14:34:39 -040036 /* Another two timer wheel geometry */
37 tw_timer_wheel_2t_2w_512sl_t two_timer_double_wheel;
38
Dave Barach8e8f98c2017-02-03 11:58:53 -050039 /** random number seed */
Dave Barach4af9ba12017-06-07 15:18:23 -040040 u64 seed;
Dave Barach8e8f98c2017-02-03 11:58:53 -050041
42 /** number of timers */
43 u32 ntimers;
44
45 /** number of "churn" iterations */
46 u32 niter;
47
48 /** number of clock ticks per churn iteration */
49 u32 ticks_per_iter;
50
51 /** cpu timer */
52 clib_time_t clib_time;
53} tw_timer_test_main_t;
54
55tw_timer_test_main_t tw_timer_test_main;
56
57static void
58run_single_wheel (tw_timer_wheel_2t_1w_2048sl_t * tw, u32 n_ticks)
59{
60 u32 i;
61 f64 now = tw->last_run_time + 1.01;
62
63 for (i = 0; i < n_ticks; i++)
64 {
65 tw_timer_expire_timers_2t_1w_2048sl (tw, now);
66 now += 1.01;
67 }
68}
69
70static void
71run_double_wheel (tw_timer_wheel_16t_2w_512sl_t * tw, u32 n_ticks)
72{
73 u32 i;
74 f64 now = tw->last_run_time + 1.01;
75
76 for (i = 0; i < n_ticks; i++)
77 {
78 tw_timer_expire_timers_16t_2w_512sl (tw, now);
79 now += 1.01;
80 }
81}
82
83static void
Dave Barach90767892020-04-01 14:34:39 -040084run_two_timer_double_wheel (tw_timer_wheel_2t_2w_512sl_t * tw, u32 n_ticks)
85{
86 u32 i;
87 f64 now = tw->last_run_time + 1.01;
88
89 for (i = 0; i < n_ticks; i++)
90 {
91 tw_timer_expire_timers_2t_2w_512sl (tw, now);
92 now += 1.01;
93 }
94}
95
96static void
Dave Barach4af9ba12017-06-07 15:18:23 -040097run_triple_wheel (tw_timer_wheel_4t_3w_256sl_t * tw, u32 n_ticks)
98{
99 u32 i;
100 f64 now = tw->last_run_time + 1.01;
101
102 for (i = 0; i < n_ticks; i++)
103 {
104 tw_timer_expire_timers_4t_3w_256sl (tw, now);
105 now += 1.01;
106 }
107}
108
109static void
110run_triple_ov_wheel (tw_timer_wheel_1t_3w_1024sl_ov_t * tw, u32 n_ticks)
111{
112 u32 i;
113 f64 now = tw->last_run_time + 1.01;
114
115 for (i = 0; i < n_ticks; i++)
116 {
117 tw_timer_expire_timers_1t_3w_1024sl_ov (tw, now);
118 now += 1.01;
119 }
120}
121
122static void
Dave Barach8e8f98c2017-02-03 11:58:53 -0500123expired_timer_single_callback (u32 * expired_timers)
124{
125 int i;
126 u32 pool_index, timer_id;
127 tw_timer_test_elt_t *e;
128 tw_timer_test_main_t *tm = &tw_timer_test_main;
129
130 for (i = 0; i < vec_len (expired_timers); i++)
131 {
132 pool_index = expired_timers[i] & 0x7FFFFFFF;
133 timer_id = expired_timers[i] >> 31;
134
135 ASSERT (timer_id == 1);
136
137 e = pool_elt_at_index (tm->test_elts, pool_index);
138
139 if (e->expected_to_expire != tm->single_wheel.current_tick)
140 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400141 fformat (stdout, "[%d] expired at %lld not %lld\n",
Dave Barach8e8f98c2017-02-03 11:58:53 -0500142 e - tm->test_elts, tm->single_wheel.current_tick,
143 e->expected_to_expire);
144 }
145 pool_put (tm->test_elts, e);
146 }
147}
148
149static void
150expired_timer_double_callback (u32 * expired_timers)
151{
152 int i;
153 u32 pool_index, timer_id;
154 tw_timer_test_elt_t *e;
155 tw_timer_test_main_t *tm = &tw_timer_test_main;
156
157 for (i = 0; i < vec_len (expired_timers); i++)
158 {
159 pool_index = expired_timers[i] & 0x0FFFFFFF;
160 timer_id = expired_timers[i] >> 28;
161
162 ASSERT (timer_id == 14);
163
164 e = pool_elt_at_index (tm->test_elts, pool_index);
165
166 if (e->expected_to_expire != tm->double_wheel.current_tick)
167 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400168 fformat (stdout, "[%d] expired at %lld not %lld\n",
Dave Barach8e8f98c2017-02-03 11:58:53 -0500169 e - tm->test_elts, tm->double_wheel.current_tick,
170 e->expected_to_expire);
171 }
172 pool_put (tm->test_elts, e);
173 }
174}
175
Dave Barach4af9ba12017-06-07 15:18:23 -0400176static void
Dave Barach90767892020-04-01 14:34:39 -0400177expired_timer_two_timer_double_callback (u32 * expired_timers)
178{
179 int i;
180 u32 pool_index, timer_id;
181 tw_timer_test_elt_t *e;
182 tw_timer_test_main_t *tm = &tw_timer_test_main;
183
184 for (i = 0; i < vec_len (expired_timers); i++)
185 {
186 pool_index = expired_timers[i] & 0x7FFFFFFF;
187 timer_id = expired_timers[i] >> 31;
188
189 ASSERT (timer_id == 1);
190
191 e = pool_elt_at_index (tm->test_elts, pool_index);
192
193 if (e->expected_to_expire != tm->two_timer_double_wheel.current_tick)
194 {
195 fformat (stdout, "[%d] expired at %lld not %lld\n",
196 e - tm->test_elts, tm->two_timer_double_wheel.current_tick,
197 e->expected_to_expire);
198 }
199 pool_put (tm->test_elts, e);
200 }
201}
202
203static void
Dave Barach4af9ba12017-06-07 15:18:23 -0400204expired_timer_triple_callback (u32 * expired_timers)
205{
206 int i;
207 u32 pool_index, timer_id;
208 tw_timer_test_elt_t *e;
209 tw_timer_test_main_t *tm = &tw_timer_test_main;
210
211 for (i = 0; i < vec_len (expired_timers); i++)
212 {
213 pool_index = expired_timers[i] & 0x3FFFFFFF;
214 timer_id = expired_timers[i] >> 30;
215
216 ASSERT (timer_id == 3);
217
218 e = pool_elt_at_index (tm->test_elts, pool_index);
219
220 if (e->expected_to_expire != tm->triple_wheel.current_tick)
221 {
222 fformat (stdout, "[%d] expired at %lld not %lld\n",
223 e - tm->test_elts, tm->triple_wheel.current_tick,
224 e->expected_to_expire);
225 }
226 pool_put (tm->test_elts, e);
227 }
228}
229
230static void
231expired_timer_triple_ov_callback (u32 * expired_timers)
232{
233 int i;
234 u32 pool_index;
235 tw_timer_test_elt_t *e;
236 tw_timer_test_main_t *tm = &tw_timer_test_main;
237
238 for (i = 0; i < vec_len (expired_timers); i++)
239 {
240 pool_index = expired_timers[i];
241
242 e = pool_elt_at_index (tm->test_elts, pool_index);
243
244 if (e->expected_to_expire != tm->triple_ov_wheel.current_tick)
245 {
246 fformat (stdout, "[%d] expired at %lld not %lld\n",
247 e - tm->test_elts, tm->triple_ov_wheel.current_tick,
248 e->expected_to_expire);
249 }
250 pool_put (tm->test_elts, e);
251 }
252}
253
Dave Barach8e8f98c2017-02-03 11:58:53 -0500254static clib_error_t *
255test2_single (tw_timer_test_main_t * tm)
256{
257 u32 i, j;
258 tw_timer_test_elt_t *e;
259 u32 initial_wheel_offset;
Dave Barach4af9ba12017-06-07 15:18:23 -0400260 u64 expiration_time;
Dave Barach8e8f98c2017-02-03 11:58:53 -0500261 u32 max_expiration_time = 0;
262 u32 *deleted_indices = 0;
263 u32 adds = 0, deletes = 0;
264 f64 before, after;
265
266 clib_time_init (&tm->clib_time);
267
268 tw_timer_wheel_init_2t_1w_2048sl (&tm->single_wheel,
269 expired_timer_single_callback,
Filip Tehlar816f4372017-04-26 16:09:06 +0200270 1.0 /* timer interval */ , ~0);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500271
272 /* Prime offset */
273 initial_wheel_offset = 757;
274
275 run_single_wheel (&tm->single_wheel, initial_wheel_offset);
276
Dave Barach4af9ba12017-06-07 15:18:23 -0400277 fformat (stdout, "initial wheel time %d, fast index %d\n",
278 tm->single_wheel.current_tick,
279 tm->single_wheel.current_index[TW_TIMER_RING_FAST]);
280
281 initial_wheel_offset = tm->single_wheel.current_tick;
282
283 fformat (stdout,
284 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
Dave Barach8e8f98c2017-02-03 11:58:53 -0500285 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
286
287 before = clib_time_now (&tm->clib_time);
288
289 /* Prime the pump */
290 for (i = 0; i < tm->ntimers; i++)
291 {
292 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400293 clib_memset (e, 0, sizeof (*e));
Dave Barach8e8f98c2017-02-03 11:58:53 -0500294
295 do
296 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400297 expiration_time = random_u64 (&tm->seed) & (2047);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500298 }
299 while (expiration_time == 0);
300
301 if (expiration_time > max_expiration_time)
302 max_expiration_time = expiration_time;
303
304 e->expected_to_expire = expiration_time + initial_wheel_offset;
305 e->stop_timer_handle =
306 tw_timer_start_2t_1w_2048sl (&tm->single_wheel, e - tm->test_elts,
307 1 /* timer id */ ,
308 expiration_time);
309 }
310
311 adds += i;
312
313 for (i = 0; i < tm->niter; i++)
314 {
315 run_single_wheel (&tm->single_wheel, tm->ticks_per_iter);
316
317 j = 0;
318 vec_reset_length (deleted_indices);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100319 pool_foreach (e, tm->test_elts)
320 {
Dave Barach8e8f98c2017-02-03 11:58:53 -0500321 tw_timer_stop_2t_1w_2048sl (&tm->single_wheel, e->stop_timer_handle);
322 vec_add1 (deleted_indices, e - tm->test_elts);
323 if (++j >= tm->ntimers / 4)
324 goto del_and_re_add;
Damjan Marionb2c31b62020-12-13 21:47:40 +0100325 }
Dave Barach8e8f98c2017-02-03 11:58:53 -0500326
327 del_and_re_add:
328 for (j = 0; j < vec_len (deleted_indices); j++)
Dave Barach4af9ba12017-06-07 15:18:23 -0400329 {
330 pool_put_index (tm->test_elts, deleted_indices[j]);
331 }
Dave Barach8e8f98c2017-02-03 11:58:53 -0500332
333 deletes += j;
334
335 for (j = 0; j < tm->ntimers / 4; j++)
336 {
337 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400338 clib_memset (e, 0, sizeof (*e));
Dave Barach8e8f98c2017-02-03 11:58:53 -0500339
340 do
341 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400342 expiration_time = random_u64 (&tm->seed) & (2047);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500343 }
344 while (expiration_time == 0);
345
346 if (expiration_time > max_expiration_time)
347 max_expiration_time = expiration_time;
348
349 e->expected_to_expire =
350 expiration_time + tm->single_wheel.current_tick;
351 e->stop_timer_handle = tw_timer_start_2t_1w_2048sl
352 (&tm->single_wheel, e - tm->test_elts, 1 /* timer id */ ,
353 expiration_time);
354 }
355 adds += j;
356 }
357
358 vec_free (deleted_indices);
359
360 run_single_wheel (&tm->single_wheel, max_expiration_time + 1);
361
362 after = clib_time_now (&tm->clib_time);
363
364 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
365 tm->single_wheel.current_tick);
366 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
367 (after - before),
368 ((f64) adds + (f64) deletes +
369 (f64) tm->single_wheel.current_tick) / (after - before));
370
371 if (pool_elts (tm->test_elts))
372 fformat (stdout, "Note: %d elements remain in pool\n",
373 pool_elts (tm->test_elts));
374
Damjan Marionb2c31b62020-12-13 21:47:40 +0100375 pool_foreach (e, tm->test_elts)
376 {
Dave Barach8e8f98c2017-02-03 11:58:53 -0500377 fformat (stdout, "[%d] expected to expire %d\n",
378 e - tm->test_elts,
379 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100380 }
Dave Barach8e8f98c2017-02-03 11:58:53 -0500381
382 pool_free (tm->test_elts);
383 tw_timer_wheel_free_2t_1w_2048sl (&tm->single_wheel);
384 return 0;
385}
386
387static clib_error_t *
388test2_double (tw_timer_test_main_t * tm)
389{
390 u32 i, j;
391 tw_timer_test_elt_t *e;
392 u32 initial_wheel_offset;
393 u32 expiration_time;
394 u32 max_expiration_time = 0;
395 u32 *deleted_indices = 0;
396 u32 adds = 0, deletes = 0;
397 f64 before, after;
398
399 clib_time_init (&tm->clib_time);
400
401 tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel,
402 expired_timer_double_callback,
Filip Tehlar816f4372017-04-26 16:09:06 +0200403 1.0 /* timer interval */ , ~0);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500404
405 /* Prime offset */
Dave Barach4af9ba12017-06-07 15:18:23 -0400406 initial_wheel_offset = 7577;
Dave Barach8e8f98c2017-02-03 11:58:53 -0500407
408 run_double_wheel (&tm->double_wheel, initial_wheel_offset);
409
Dave Barach4af9ba12017-06-07 15:18:23 -0400410 fformat (stdout, "initial wheel time %d, fast index %d slow index %d\n",
411 tm->double_wheel.current_tick,
412 tm->double_wheel.current_index[TW_TIMER_RING_FAST],
413 tm->double_wheel.current_index[TW_TIMER_RING_SLOW]);
414
415 initial_wheel_offset = tm->double_wheel.current_tick;
416
417 fformat (stdout,
418 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
Dave Barach8e8f98c2017-02-03 11:58:53 -0500419 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
420
421 before = clib_time_now (&tm->clib_time);
422
423 /* Prime the pump */
424 for (i = 0; i < tm->ntimers; i++)
425 {
426 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400427 clib_memset (e, 0, sizeof (*e));
Dave Barach8e8f98c2017-02-03 11:58:53 -0500428
429 do
430 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400431 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500432 }
433 while (expiration_time == 0);
434
435 if (expiration_time > max_expiration_time)
436 max_expiration_time = expiration_time;
437
438 e->expected_to_expire = expiration_time + initial_wheel_offset;
Dave Barach4af9ba12017-06-07 15:18:23 -0400439
Dave Barach8e8f98c2017-02-03 11:58:53 -0500440 e->stop_timer_handle =
441 tw_timer_start_16t_2w_512sl (&tm->double_wheel, e - tm->test_elts,
442 14 /* timer id */ ,
443 expiration_time);
444 }
445
446 adds += i;
447
448 for (i = 0; i < tm->niter; i++)
449 {
450 run_double_wheel (&tm->double_wheel, tm->ticks_per_iter);
451
452 j = 0;
453 vec_reset_length (deleted_indices);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100454 pool_foreach (e, tm->test_elts)
455 {
Dave Barach8e8f98c2017-02-03 11:58:53 -0500456 tw_timer_stop_16t_2w_512sl (&tm->double_wheel, e->stop_timer_handle);
457 vec_add1 (deleted_indices, e - tm->test_elts);
458 if (++j >= tm->ntimers / 4)
459 goto del_and_re_add;
Damjan Marionb2c31b62020-12-13 21:47:40 +0100460 }
Dave Barach8e8f98c2017-02-03 11:58:53 -0500461
462 del_and_re_add:
463 for (j = 0; j < vec_len (deleted_indices); j++)
464 pool_put_index (tm->test_elts, deleted_indices[j]);
465
466 deletes += j;
467
468 for (j = 0; j < tm->ntimers / 4; j++)
469 {
470 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400471 clib_memset (e, 0, sizeof (*e));
Dave Barach8e8f98c2017-02-03 11:58:53 -0500472
473 do
474 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400475 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500476 }
477 while (expiration_time == 0);
478
479 if (expiration_time > max_expiration_time)
480 max_expiration_time = expiration_time;
481
482 e->expected_to_expire = expiration_time +
483 tm->double_wheel.current_tick;
Dave Barach4af9ba12017-06-07 15:18:23 -0400484
Dave Barach8e8f98c2017-02-03 11:58:53 -0500485 e->stop_timer_handle = tw_timer_start_16t_2w_512sl
486 (&tm->double_wheel, e - tm->test_elts, 14 /* timer id */ ,
487 expiration_time);
488 }
489 adds += j;
490 }
491
492 vec_free (deleted_indices);
493
494 run_double_wheel (&tm->double_wheel, max_expiration_time + 1);
495
496 after = clib_time_now (&tm->clib_time);
497
498 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
499 tm->double_wheel.current_tick);
500 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
501 (after - before),
502 ((f64) adds + (f64) deletes +
503 (f64) tm->double_wheel.current_tick) / (after - before));
504
505 if (pool_elts (tm->test_elts))
506 fformat (stdout, "Note: %d elements remain in pool\n",
507 pool_elts (tm->test_elts));
508
Damjan Marionb2c31b62020-12-13 21:47:40 +0100509 pool_foreach (e, tm->test_elts)
510 {
Dave Barach8e8f98c2017-02-03 11:58:53 -0500511 fformat (stdout, "[%d] expected to expire %d\n",
512 e - tm->test_elts,
513 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100514 }
Dave Barach8e8f98c2017-02-03 11:58:53 -0500515
516 pool_free (tm->test_elts);
517 tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel);
518 return 0;
519}
520
Florin Corasadb5bd52018-06-22 15:29:38 -0700521static u32
522get_expiration_time (tw_timer_test_main_t * tm)
523{
524 u32 expiration_time;
525 do
526 {
527 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
528 }
529 while (expiration_time == 0);
530 return expiration_time;
531}
532
533static clib_error_t *
534test2_double_updates (tw_timer_test_main_t * tm)
535{
536 u32 i, j;
537 tw_timer_test_elt_t *e;
538 u32 initial_wheel_offset;
539 u32 expiration_time;
540 u32 max_expiration_time = 0, updates = 0;
541 f64 before, after;
542
543 clib_time_init (&tm->clib_time);
544 tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel,
545 expired_timer_double_callback,
546 1.0 /* timer interval */ , ~0);
547
548 /* Prime offset */
549 initial_wheel_offset = 7577;
550 run_double_wheel (&tm->double_wheel, initial_wheel_offset);
551 fformat (stdout, "initial wheel time %d, fast index %d slow index %d\n",
552 tm->double_wheel.current_tick,
553 tm->double_wheel.current_index[TW_TIMER_RING_FAST],
554 tm->double_wheel.current_index[TW_TIMER_RING_SLOW]);
555
556 initial_wheel_offset = tm->double_wheel.current_tick;
557 fformat (stdout,
558 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
559 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
560
561 before = clib_time_now (&tm->clib_time);
562
563 /* Prime the pump */
564 for (i = 0; i < tm->ntimers; i++)
565 {
566 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400567 clib_memset (e, 0, sizeof (*e));
Florin Corasadb5bd52018-06-22 15:29:38 -0700568
569 expiration_time = get_expiration_time (tm);
570 max_expiration_time = clib_max (expiration_time, max_expiration_time);
571
572 e->expected_to_expire = expiration_time + initial_wheel_offset;
573 e->stop_timer_handle = tw_timer_start_16t_2w_512sl (&tm->double_wheel,
574 e - tm->test_elts,
575 14 /* timer id */ ,
576 expiration_time);
577 }
578
579 for (i = 0; i < tm->niter; i++)
580 {
581 run_double_wheel (&tm->double_wheel, tm->ticks_per_iter);
582
583 j = 0;
584
Damjan Marionb2c31b62020-12-13 21:47:40 +0100585 pool_foreach (e, tm->test_elts)
586 {
Florin Corasadb5bd52018-06-22 15:29:38 -0700587 expiration_time = get_expiration_time (tm);
588 max_expiration_time = clib_max (expiration_time, max_expiration_time);
589 e->expected_to_expire = expiration_time
590 + tm->double_wheel.current_tick;
591 tw_timer_update_16t_2w_512sl (&tm->double_wheel, e->stop_timer_handle,
592 expiration_time);
593 if (++j >= tm->ntimers / 4)
594 goto done;
Damjan Marionb2c31b62020-12-13 21:47:40 +0100595 }
Florin Corasadb5bd52018-06-22 15:29:38 -0700596
597 done:
598 updates += j;
599 }
600
601 run_double_wheel (&tm->double_wheel, max_expiration_time + 1);
602
603 after = clib_time_now (&tm->clib_time);
604
605 fformat (stdout, "%d updates, %d ticks\n", updates,
606 tm->double_wheel.current_tick);
607 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
608 (after - before),
609 ((f64) updates + (f64) tm->double_wheel.current_tick) / (after -
610 before));
611
612 if (pool_elts (tm->test_elts))
613 fformat (stdout, "Note: %d elements remain in pool\n",
614 pool_elts (tm->test_elts));
615
Damjan Marionb2c31b62020-12-13 21:47:40 +0100616 pool_foreach (e, tm->test_elts)
617 {
Florin Corasadb5bd52018-06-22 15:29:38 -0700618 fformat (stdout, "[%d] expected to expire %d\n",
619 e - tm->test_elts,
620 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100621 }
Florin Corasadb5bd52018-06-22 15:29:38 -0700622
623 pool_free (tm->test_elts);
624 tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel);
625 return 0;
626}
627
Dave Barach8e8f98c2017-02-03 11:58:53 -0500628static clib_error_t *
Dave Barach4af9ba12017-06-07 15:18:23 -0400629test2_triple (tw_timer_test_main_t * tm)
630{
631 u32 i, j;
632 tw_timer_test_elt_t *e;
633 u32 initial_wheel_offset = 0;
634 u32 expiration_time;
635 u32 max_expiration_time = 0;
636 u32 *deleted_indices = 0;
637 u32 adds = 0, deletes = 0;
638 f64 before, after;
639
640 clib_time_init (&tm->clib_time);
641
642 tw_timer_wheel_init_4t_3w_256sl (&tm->triple_wheel,
643 expired_timer_triple_callback,
644 1.0 /* timer interval */ , ~0);
645
646
647 /* Prime offset */
648 initial_wheel_offset = 75700;
649 run_triple_wheel (&tm->triple_wheel, initial_wheel_offset);
650
651 fformat (stdout,
652 "initial wheel time %d, fi %d si %d gi %d\n",
653 tm->triple_wheel.current_tick,
654 tm->triple_wheel.current_index[TW_TIMER_RING_FAST],
655 tm->triple_wheel.current_index[TW_TIMER_RING_SLOW],
656 tm->triple_wheel.current_index[TW_TIMER_RING_GLACIER]);
657
658 initial_wheel_offset = tm->triple_wheel.current_tick;
659
660 fformat (stdout,
661 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
662 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
663
664 before = clib_time_now (&tm->clib_time);
665
666 /* Prime the pump */
667 for (i = 0; i < tm->ntimers; i++)
668 {
669 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400670 clib_memset (e, 0, sizeof (*e));
Dave Barach4af9ba12017-06-07 15:18:23 -0400671
672 do
673 {
674 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
675 }
676 while (expiration_time == 0);
677
678 if (expiration_time > max_expiration_time)
679 max_expiration_time = expiration_time;
680
681 e->expected_to_expire = expiration_time + initial_wheel_offset;
682
683 e->stop_timer_handle =
684 tw_timer_start_4t_3w_256sl (&tm->triple_wheel, e - tm->test_elts,
685 3 /* timer id */ ,
686 expiration_time);
687 }
688
689 adds += i;
690
691 for (i = 0; i < tm->niter; i++)
692 {
693 run_triple_wheel (&tm->triple_wheel, tm->ticks_per_iter);
694
695 j = 0;
696 vec_reset_length (deleted_indices);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100697 pool_foreach (e, tm->test_elts)
698 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400699 tw_timer_stop_4t_3w_256sl (&tm->triple_wheel, e->stop_timer_handle);
700 vec_add1 (deleted_indices, e - tm->test_elts);
701 if (++j >= tm->ntimers / 4)
702 goto del_and_re_add;
Damjan Marionb2c31b62020-12-13 21:47:40 +0100703 }
Dave Barach4af9ba12017-06-07 15:18:23 -0400704
705 del_and_re_add:
706 for (j = 0; j < vec_len (deleted_indices); j++)
707 pool_put_index (tm->test_elts, deleted_indices[j]);
708
709 deletes += j;
710
711 for (j = 0; j < tm->ntimers / 4; j++)
712 {
713 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400714 clib_memset (e, 0, sizeof (*e));
Dave Barach4af9ba12017-06-07 15:18:23 -0400715
716 do
717 {
718 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
719 }
720 while (expiration_time == 0);
721
722 if (expiration_time > max_expiration_time)
723 max_expiration_time = expiration_time;
724
725 e->expected_to_expire = expiration_time +
726 tm->triple_wheel.current_tick;
727
728 e->stop_timer_handle = tw_timer_start_4t_3w_256sl
729 (&tm->triple_wheel, e - tm->test_elts, 3 /* timer id */ ,
730 expiration_time);
731 }
732 adds += j;
733 }
734
735 vec_free (deleted_indices);
736
737 run_triple_wheel (&tm->triple_wheel, max_expiration_time + 1);
738
739 after = clib_time_now (&tm->clib_time);
740
741 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
742 tm->triple_wheel.current_tick);
743 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
744 (after - before),
745 ((f64) adds + (f64) deletes +
746 (f64) tm->triple_wheel.current_tick) / (after - before));
747
748 if (pool_elts (tm->test_elts))
749 fformat (stdout, "Note: %d elements remain in pool\n",
750 pool_elts (tm->test_elts));
751
Damjan Marionb2c31b62020-12-13 21:47:40 +0100752 pool_foreach (e, tm->test_elts)
753 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400754 fformat (stdout, "[%d] expected to expire %d\n",
755 e - tm->test_elts,
756 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100757 }
Dave Barach4af9ba12017-06-07 15:18:23 -0400758
759 pool_free (tm->test_elts);
760 tw_timer_wheel_free_4t_3w_256sl (&tm->triple_wheel);
761 return 0;
762}
763
764static clib_error_t *
765test2_triple_ov (tw_timer_test_main_t * tm)
766{
767 u32 i, j;
768 tw_timer_test_elt_t *e;
769 u32 initial_wheel_offset = 0;
770 u32 expiration_time;
771 u32 max_expiration_time = 0;
772 u32 *deleted_indices = 0;
773 u32 adds = 0, deletes = 0;
774 f64 before, after;
775
776 clib_time_init (&tm->clib_time);
777
778 tw_timer_wheel_init_1t_3w_1024sl_ov (&tm->triple_ov_wheel,
779 expired_timer_triple_ov_callback,
780 1.0 /* timer interval */ , ~0);
781
782
783 /* Prime offset */
784 initial_wheel_offset = 75700;
785 run_triple_ov_wheel (&tm->triple_ov_wheel, initial_wheel_offset);
786
787 fformat (stdout,
788 "initial wheel time %d, fi %d si %d gi %d\n",
789 tm->triple_ov_wheel.current_tick,
790 tm->triple_ov_wheel.current_index[TW_TIMER_RING_FAST],
791 tm->triple_ov_wheel.current_index[TW_TIMER_RING_SLOW],
792 tm->triple_ov_wheel.current_index[TW_TIMER_RING_GLACIER]);
793
794 initial_wheel_offset = tm->triple_ov_wheel.current_tick;
795
796 fformat (stdout,
797 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
798 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
799
800 before = clib_time_now (&tm->clib_time);
801
802 /* Prime the pump */
803 for (i = 0; i < tm->ntimers; i++)
804 {
805 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400806 clib_memset (e, 0, sizeof (*e));
Dave Barach4af9ba12017-06-07 15:18:23 -0400807
808 do
809 {
810 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
811 }
812 while (expiration_time == 0);
813
814 if (expiration_time > max_expiration_time)
815 max_expiration_time = expiration_time;
816
817 e->expected_to_expire = expiration_time + initial_wheel_offset;
818
819 e->stop_timer_handle =
820 tw_timer_start_1t_3w_1024sl_ov (&tm->triple_ov_wheel,
821 e - tm->test_elts, 0 /* timer id */ ,
822 expiration_time);
823 }
824
825 adds += i;
826
827 for (i = 0; i < tm->niter; i++)
828 {
829 run_triple_ov_wheel (&tm->triple_ov_wheel, tm->ticks_per_iter);
830
831 j = 0;
832 vec_reset_length (deleted_indices);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100833 pool_foreach (e, tm->test_elts)
834 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400835 tw_timer_stop_1t_3w_1024sl_ov (&tm->triple_ov_wheel,
836 e->stop_timer_handle);
837 vec_add1 (deleted_indices, e - tm->test_elts);
838 if (++j >= tm->ntimers / 4)
839 goto del_and_re_add;
Damjan Marionb2c31b62020-12-13 21:47:40 +0100840 }
Dave Barach4af9ba12017-06-07 15:18:23 -0400841
842 del_and_re_add:
843 for (j = 0; j < vec_len (deleted_indices); j++)
844 pool_put_index (tm->test_elts, deleted_indices[j]);
845
846 deletes += j;
847
848 for (j = 0; j < tm->ntimers / 4; j++)
849 {
850 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400851 clib_memset (e, 0, sizeof (*e));
Dave Barach4af9ba12017-06-07 15:18:23 -0400852
853 do
854 {
855 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
856 }
857 while (expiration_time == 0);
858
859 if (expiration_time > max_expiration_time)
860 max_expiration_time = expiration_time;
861
862 e->expected_to_expire = expiration_time +
863 tm->triple_ov_wheel.current_tick;
864
865 e->stop_timer_handle = tw_timer_start_1t_3w_1024sl_ov
866 (&tm->triple_ov_wheel, e - tm->test_elts, 0 /* timer id */ ,
867 expiration_time);
868 }
869 adds += j;
870 }
871
872 vec_free (deleted_indices);
873
874 run_triple_ov_wheel (&tm->triple_ov_wheel, max_expiration_time + 1);
875
876 after = clib_time_now (&tm->clib_time);
877
878 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
879 tm->triple_ov_wheel.current_tick);
880 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
881 (after - before),
882 ((f64) adds + (f64) deletes +
883 (f64) tm->triple_ov_wheel.current_tick) / (after - before));
884
885 if (pool_elts (tm->test_elts))
886 fformat (stdout, "Note: %d elements remain in pool\n",
887 pool_elts (tm->test_elts));
888
Damjan Marionb2c31b62020-12-13 21:47:40 +0100889 pool_foreach (e, tm->test_elts)
890 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400891 TWT (tw_timer) * t;
892
893 fformat (stdout, "[%d] expected to expire %d\n",
894 e - tm->test_elts,
895 e->expected_to_expire);
896 t = pool_elt_at_index (tm->triple_ov_wheel.timers, e->stop_timer_handle);
897 fformat (stdout, " expiration_time %lld\n", t->expiration_time);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100898 }
Dave Barach4af9ba12017-06-07 15:18:23 -0400899
900 pool_free (tm->test_elts);
901 tw_timer_wheel_free_1t_3w_1024sl_ov (&tm->triple_ov_wheel);
902 return 0;
903}
904
905static clib_error_t *
Dave Barach8e8f98c2017-02-03 11:58:53 -0500906test1_single (tw_timer_test_main_t * tm)
907{
908 u32 i;
909 tw_timer_test_elt_t *e;
910 u32 offset;
911
912 tw_timer_wheel_init_2t_1w_2048sl (&tm->single_wheel,
913 expired_timer_single_callback,
Filip Tehlar816f4372017-04-26 16:09:06 +0200914 1.0 /* timer interval */ , ~0);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500915
916 /*
917 * Prime offset, to make sure that the wheel starts in a
918 * non-trivial position
919 */
920 offset = 123;
921
922 run_single_wheel (&tm->single_wheel, offset);
923
924 fformat (stdout, "initial wheel time %d, fast index %d\n",
925 tm->single_wheel.current_tick,
926 tm->single_wheel.current_index[TW_TIMER_RING_FAST]);
927
Dave Barach4af9ba12017-06-07 15:18:23 -0400928 offset = tm->single_wheel.current_tick;
929
Dave Barach8e8f98c2017-02-03 11:58:53 -0500930 for (i = 0; i < tm->ntimers; i++)
931 {
932 u32 expected_to_expire;
933 u32 timer_arg;
934
935 timer_arg = 1 + i;
936 timer_arg &= 2047;
937 if (timer_arg == 0)
938 timer_arg = 1;
939
Dave Barach90767892020-04-01 14:34:39 -0400940 expected_to_expire = timer_arg + tm->single_wheel.current_tick;
Dave Barach8e8f98c2017-02-03 11:58:53 -0500941
942 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400943 clib_memset (e, 0, sizeof (*e));
Dave Barach8e8f98c2017-02-03 11:58:53 -0500944 e->expected_to_expire = expected_to_expire;
945 e->stop_timer_handle = tw_timer_start_2t_1w_2048sl
946 (&tm->single_wheel, e - tm->test_elts, 1 /* timer id */ ,
947 timer_arg);
948 }
949 run_single_wheel (&tm->single_wheel, tm->ntimers + 3);
950
951 if (pool_elts (tm->test_elts))
952 fformat (stdout, "Note: %d elements remain in pool\n",
953 pool_elts (tm->test_elts));
954
Damjan Marionb2c31b62020-12-13 21:47:40 +0100955 pool_foreach (e, tm->test_elts)
956 {
Dave Barach8e8f98c2017-02-03 11:58:53 -0500957 fformat(stdout, "[%d] expected to expire %d\n",
958 e - tm->test_elts,
959 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100960 }
Dave Barach8e8f98c2017-02-03 11:58:53 -0500961
962 fformat (stdout,
963 "final wheel time %d, fast index %d\n",
964 tm->single_wheel.current_tick,
965 tm->single_wheel.current_index[TW_TIMER_RING_FAST]);
966
967 pool_free (tm->test_elts);
968 tw_timer_wheel_free_2t_1w_2048sl (&tm->single_wheel);
969 return 0;
970}
971
972static clib_error_t *
973test1_double (tw_timer_test_main_t * tm)
974{
975 u32 i;
976 tw_timer_test_elt_t *e;
977 u32 offset;
978
979 tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel,
980 expired_timer_double_callback,
Filip Tehlar816f4372017-04-26 16:09:06 +0200981 1.0 /* timer interval */ , ~0);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500982
983 /*
984 * Prime offset, to make sure that the wheel starts in a
985 * non-trivial position
986 */
987 offset = 227989;
988
989 run_double_wheel (&tm->double_wheel, offset);
990
991 fformat (stdout, "initial wheel time %d, fast index %d\n",
992 tm->double_wheel.current_tick,
993 tm->double_wheel.current_index[TW_TIMER_RING_FAST]);
994
995 for (i = 0; i < tm->ntimers; i++)
996 {
997 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400998 clib_memset (e, 0, sizeof (*e));
Dave Barach8e8f98c2017-02-03 11:58:53 -0500999
Dave Barach90767892020-04-01 14:34:39 -04001000 e->expected_to_expire = i + tm->double_wheel.current_tick + 1;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001001 e->stop_timer_handle = tw_timer_start_16t_2w_512sl
1002 (&tm->double_wheel, e - tm->test_elts, 14 /* timer id */ ,
1003 i + 1);
1004 }
1005 run_double_wheel (&tm->double_wheel, tm->ntimers + 3);
1006
1007 if (pool_elts (tm->test_elts))
1008 fformat (stdout, "Note: %d elements remain in pool\n",
1009 pool_elts (tm->test_elts));
1010
Damjan Marionb2c31b62020-12-13 21:47:40 +01001011 pool_foreach (e, tm->test_elts)
1012 {
Dave Barach8e8f98c2017-02-03 11:58:53 -05001013 fformat(stdout, "[%d] expected to expire %d\n",
1014 e - tm->test_elts,
1015 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +01001016 }
Dave Barach8e8f98c2017-02-03 11:58:53 -05001017
1018 fformat (stdout,
1019 "final wheel time %d, fast index %d\n",
1020 tm->double_wheel.current_tick,
1021 tm->double_wheel.current_index[TW_TIMER_RING_FAST]);
1022
1023 pool_free (tm->test_elts);
1024 tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel);
1025 return 0;
1026}
1027
1028static clib_error_t *
Dave Barach90767892020-04-01 14:34:39 -04001029test1_two_timer_double (tw_timer_test_main_t * tm)
1030{
1031 u32 i;
1032 tw_timer_test_elt_t *e;
1033 u32 offset;
1034
1035 tw_timer_wheel_init_2t_2w_512sl (&tm->two_timer_double_wheel,
1036 expired_timer_two_timer_double_callback,
1037 1.0 /* timer interval */ , ~0);
1038
1039 /*
1040 * Prime offset, to make sure that the wheel starts in a
1041 * non-trivial position
1042 */
1043 offset = 2745;
1044
1045 run_two_timer_double_wheel (&tm->two_timer_double_wheel, offset);
1046
1047 fformat (stdout, "initial wheel time %d, fast index %d\n",
1048 tm->two_timer_double_wheel.current_tick,
1049 tm->two_timer_double_wheel.current_index[TW_TIMER_RING_FAST]);
1050
1051 for (i = 0; i < tm->ntimers; i++)
1052 {
1053 pool_get (tm->test_elts, e);
1054 clib_memset (e, 0, sizeof (*e));
1055
1056 e->expected_to_expire = i + tm->two_timer_double_wheel.current_tick + 1;
1057 e->stop_timer_handle = tw_timer_start_2t_2w_512sl
1058 (&tm->two_timer_double_wheel, e - tm->test_elts, 1 /* timer id */ ,
1059 i + 1);
1060 }
1061 run_two_timer_double_wheel (&tm->two_timer_double_wheel, tm->ntimers + 3);
1062
1063 if (pool_elts (tm->test_elts))
1064 fformat (stdout, "Note: %d elements remain in pool\n",
1065 pool_elts (tm->test_elts));
1066
Damjan Marionb2c31b62020-12-13 21:47:40 +01001067 pool_foreach (e, tm->test_elts)
1068 {
Dave Barach90767892020-04-01 14:34:39 -04001069 fformat(stdout, "[%d] expected to expire %d\n",
1070 e - tm->test_elts,
1071 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +01001072 }
Dave Barach90767892020-04-01 14:34:39 -04001073
1074 fformat (stdout,
1075 "final wheel time %d, fast index %d\n",
1076 tm->two_timer_double_wheel.current_tick,
1077 tm->two_timer_double_wheel.current_index[TW_TIMER_RING_FAST]);
1078
1079 pool_free (tm->test_elts);
1080 tw_timer_wheel_free_2t_2w_512sl (&tm->two_timer_double_wheel);
1081 return 0;
1082}
1083
1084static clib_error_t *
Dave Barach4af9ba12017-06-07 15:18:23 -04001085test3_triple_double (tw_timer_test_main_t * tm)
1086{
1087 tw_timer_test_elt_t *e;
1088 u32 initial_wheel_offset = 0;
1089 u32 expiration_time;
1090 u32 max_expiration_time = 0;
1091 u32 adds = 0, deletes = 0;
1092 f64 before, after;
1093
1094 clib_time_init (&tm->clib_time);
1095
1096 tw_timer_wheel_init_4t_3w_256sl (&tm->triple_wheel,
1097 expired_timer_triple_callback,
1098 1.0 /* timer interval */ , ~0);
1099
1100 initial_wheel_offset = 0;
1101 run_triple_wheel (&tm->triple_wheel, initial_wheel_offset);
1102
1103 fformat (stdout,
1104 "initial wheel time %d, fi %d si %d gi %d\n",
1105 tm->triple_wheel.current_tick,
1106 tm->triple_wheel.current_index[TW_TIMER_RING_FAST],
1107 tm->triple_wheel.current_index[TW_TIMER_RING_SLOW],
1108 tm->triple_wheel.current_index[TW_TIMER_RING_GLACIER]);
1109
1110 initial_wheel_offset = tm->triple_wheel.current_tick;
1111
1112 fformat (stdout, "Create a timer which expires at wheel-time (1, 0, 0)\n");
1113
1114 before = clib_time_now (&tm->clib_time);
1115
1116 /* Prime the pump */
1117 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -04001118 clib_memset (e, 0, sizeof (*e));
Dave Barach4af9ba12017-06-07 15:18:23 -04001119
1120 /* 1 glacier ring tick from now */
1121 expiration_time = TW_SLOTS_PER_RING * TW_SLOTS_PER_RING;
1122 e->expected_to_expire = expiration_time + initial_wheel_offset;
1123 max_expiration_time = expiration_time;
1124
1125 e->stop_timer_handle =
1126 tw_timer_start_4t_3w_256sl (&tm->triple_wheel, e - tm->test_elts,
1127 3 /* timer id */ ,
1128 expiration_time);
1129
1130 run_triple_wheel (&tm->triple_wheel, max_expiration_time + 1);
1131
1132 after = clib_time_now (&tm->clib_time);
1133
1134 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
1135 tm->triple_wheel.current_tick);
1136 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
1137 (after - before),
1138 ((f64) adds + (f64) deletes +
1139 (f64) tm->triple_wheel.current_tick) / (after - before));
1140
1141 if (pool_elts (tm->test_elts))
1142 fformat (stdout, "Note: %d elements remain in pool\n",
1143 pool_elts (tm->test_elts));
1144
Damjan Marionb2c31b62020-12-13 21:47:40 +01001145 pool_foreach (e, tm->test_elts)
1146 {
Dave Barach4af9ba12017-06-07 15:18:23 -04001147 fformat (stdout, "[%d] expected to expire %d\n",
1148 e - tm->test_elts,
1149 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +01001150 }
Dave Barach4af9ba12017-06-07 15:18:23 -04001151
1152 pool_free (tm->test_elts);
1153 tw_timer_wheel_free_4t_3w_256sl (&tm->triple_wheel);
1154 return 0;
1155}
1156
1157static clib_error_t *
1158test4_double_double (tw_timer_test_main_t * tm)
1159{
1160 u32 i;
1161 tw_timer_test_elt_t *e;
1162 u32 initial_wheel_offset;
1163 u32 expiration_time;
1164 u32 max_expiration_time = 0;
1165 u32 *deleted_indices = 0;
1166 u32 adds = 0, deletes = 0;
1167 f64 before, after;
1168
1169 clib_time_init (&tm->clib_time);
1170
1171 tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel,
1172 expired_timer_double_callback,
1173 1.0 /* timer interval */ , ~0);
1174 /* Prime offset */
1175 initial_wheel_offset = 0;
1176
1177 run_double_wheel (&tm->double_wheel, initial_wheel_offset);
1178
1179 fformat (stdout, "initial wheel time %d, fast index %d slow index %d\n",
1180 tm->double_wheel.current_tick,
1181 tm->double_wheel.current_index[TW_TIMER_RING_FAST],
1182 tm->double_wheel.current_index[TW_TIMER_RING_SLOW]);
1183
1184 initial_wheel_offset = tm->double_wheel.current_tick;
1185
1186 fformat (stdout, "test timer which expires at 512 ticks\n");
1187
1188 before = clib_time_now (&tm->clib_time);
1189
1190 /* Prime the pump */
1191 for (i = 0; i < tm->ntimers; i++)
1192 {
1193 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -04001194 clib_memset (e, 0, sizeof (*e));
Dave Barach4af9ba12017-06-07 15:18:23 -04001195
1196 expiration_time = 512;
1197
1198 if (expiration_time > max_expiration_time)
1199 max_expiration_time = expiration_time;
1200
1201 e->expected_to_expire = expiration_time + initial_wheel_offset;
1202 e->stop_timer_handle =
1203 tw_timer_start_16t_2w_512sl (&tm->double_wheel, e - tm->test_elts,
1204 14 /* timer id */ ,
1205 expiration_time);
1206 }
1207
1208 adds = 1;
1209
1210 vec_free (deleted_indices);
1211
1212 run_double_wheel (&tm->double_wheel, max_expiration_time + 1);
1213
1214 after = clib_time_now (&tm->clib_time);
1215
1216 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
1217 tm->double_wheel.current_tick);
1218 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
1219 (after - before),
1220 ((f64) adds + (f64) deletes +
1221 (f64) tm->double_wheel.current_tick) / (after - before));
1222
1223 if (pool_elts (tm->test_elts))
1224 fformat (stdout, "Note: %d elements remain in pool\n",
1225 pool_elts (tm->test_elts));
1226
Damjan Marionb2c31b62020-12-13 21:47:40 +01001227 pool_foreach (e, tm->test_elts)
1228 {
Dave Barach4af9ba12017-06-07 15:18:23 -04001229 fformat (stdout, "[%d] expected to expire %d\n",
1230 e - tm->test_elts,
1231 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +01001232 }
Dave Barach4af9ba12017-06-07 15:18:23 -04001233
1234 pool_free (tm->test_elts);
1235 tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel);
1236 return 0;
1237}
1238
1239static clib_error_t *
1240test5_double (tw_timer_test_main_t * tm)
1241{
1242 u32 i;
1243 tw_timer_test_elt_t *e;
1244 u32 initial_wheel_offset;
1245 u32 expiration_time;
1246 u32 max_expiration_time = 0;
1247 u32 adds = 0, deletes = 0;
1248 f64 before, after;
1249
1250 clib_time_init (&tm->clib_time);
1251
1252 tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel,
1253 expired_timer_double_callback,
1254 1.0 /* timer interval */ , ~0);
1255
1256 /* Prime offset */
1257 initial_wheel_offset = 7567;
1258
1259 run_double_wheel (&tm->double_wheel, initial_wheel_offset);
1260
1261 fformat (stdout, "initial wheel time %d, fast index %d slow index %d\n",
1262 tm->double_wheel.current_tick,
1263 tm->double_wheel.current_index[TW_TIMER_RING_FAST],
1264 tm->double_wheel.current_index[TW_TIMER_RING_SLOW]);
1265
1266 initial_wheel_offset = tm->double_wheel.current_tick;
1267
1268 fformat (stdout,
1269 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
1270 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
1271
1272 before = clib_time_now (&tm->clib_time);
1273
1274 /* Prime the pump */
1275 for (i = 0; i < tm->ntimers; i++)
1276 {
1277 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -04001278 clib_memset (e, 0, sizeof (*e));
Dave Barach4af9ba12017-06-07 15:18:23 -04001279
1280 expiration_time = i + 1;
1281
1282 if (expiration_time > max_expiration_time)
1283 max_expiration_time = expiration_time;
1284
1285 e->expected_to_expire = expiration_time + initial_wheel_offset;
1286 e->stop_timer_handle =
1287 tw_timer_start_16t_2w_512sl (&tm->double_wheel, e - tm->test_elts,
1288 14 /* timer id */ ,
1289 expiration_time);
1290 }
1291
1292 adds += i;
1293
1294 run_double_wheel (&tm->double_wheel, max_expiration_time + 1);
1295
1296 after = clib_time_now (&tm->clib_time);
1297
1298 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
1299 tm->double_wheel.current_tick);
1300 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
1301 (after - before),
1302 ((f64) adds + (f64) deletes +
1303 (f64) tm->double_wheel.current_tick) / (after - before));
1304
1305 if (pool_elts (tm->test_elts))
1306 fformat (stdout, "Note: %d elements remain in pool\n",
1307 pool_elts (tm->test_elts));
1308
Damjan Marionb2c31b62020-12-13 21:47:40 +01001309 pool_foreach (e, tm->test_elts)
1310 {
Dave Barach4af9ba12017-06-07 15:18:23 -04001311 fformat (stdout, "[%d] expected to expire %d\n",
1312 e - tm->test_elts,
1313 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +01001314 }
Dave Barach4af9ba12017-06-07 15:18:23 -04001315
1316 pool_free (tm->test_elts);
1317 tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel);
1318 return 0;
1319}
1320
1321static clib_error_t *
Dave Barach8e8f98c2017-02-03 11:58:53 -05001322timer_test_command_fn (tw_timer_test_main_t * tm, unformat_input_t * input)
1323{
1324
Florin Corasadb5bd52018-06-22 15:29:38 -07001325 int is_test1 = 0, is_updates = 0;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001326 int num_wheels = 1;
1327 int is_test2 = 0;
Dave Barach4af9ba12017-06-07 15:18:23 -04001328 int is_test3 = 0;
1329 int is_test4 = 0;
1330 int is_test5 = 0;
1331 int overflow = 0;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001332
Dave Barachb7b92992018-10-17 10:38:51 -04001333 clib_memset (tm, 0, sizeof (*tm));
Dave Barach8e8f98c2017-02-03 11:58:53 -05001334 /* Default values */
1335 tm->ntimers = 100000;
Dave Barach4af9ba12017-06-07 15:18:23 -04001336 tm->seed = 0xDEADDABEB00BFACE;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001337 tm->niter = 1000;
1338 tm->ticks_per_iter = 727;
1339
1340 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1341 {
Dave Barach4af9ba12017-06-07 15:18:23 -04001342 if (unformat (input, "seed %lld", &tm->seed))
Dave Barach8e8f98c2017-02-03 11:58:53 -05001343 ;
1344 else if (unformat (input, "test1"))
1345 is_test1 = 1;
1346 else if (unformat (input, "test2"))
1347 is_test2 = 1;
Dave Barach4af9ba12017-06-07 15:18:23 -04001348 else if (unformat (input, "overflow"))
1349 overflow = 1;
1350 else if (unformat (input, "lebron"))
1351 is_test3 = 1;
1352 else if (unformat (input, "wilt"))
1353 is_test4 = 1;
1354 else if (unformat (input, "linear"))
1355 is_test5 = 1;
Florin Corasadb5bd52018-06-22 15:29:38 -07001356 else if (unformat (input, "updates"))
1357 is_updates = 1;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001358 else if (unformat (input, "wheels %d", &num_wheels))
1359 ;
1360 else if (unformat (input, "ntimers %d", &tm->ntimers))
1361 ;
1362 else if (unformat (input, "niter %d", &tm->niter))
1363 ;
1364 else if (unformat (input, "ticks_per_iter %d", &tm->ticks_per_iter))
1365 ;
Dave Barach4af9ba12017-06-07 15:18:23 -04001366 else
1367 break;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001368 }
1369
Dave Barach4af9ba12017-06-07 15:18:23 -04001370 if (is_test1 + is_test2 + is_test3 + is_test4 + is_test5 == 0)
Dave Barach8e8f98c2017-02-03 11:58:53 -05001371 return clib_error_return (0, "No test specified [test1..n]");
1372
Dave Barach4af9ba12017-06-07 15:18:23 -04001373 if (num_wheels < 1 || num_wheels > 3)
Dave Barach8e8f98c2017-02-03 11:58:53 -05001374 return clib_error_return (0, "unsupported... 1 or 2 wheels only");
1375
1376 if (is_test1)
1377 {
1378 if (num_wheels == 1)
1379 return test1_single (tm);
1380 else
Dave Barach90767892020-04-01 14:34:39 -04001381 {
1382 (void) test1_double (tm);
1383 return test1_two_timer_double (tm);
1384 }
Dave Barach8e8f98c2017-02-03 11:58:53 -05001385 }
1386 if (is_test2)
1387 {
1388 if (num_wheels == 1)
1389 return test2_single (tm);
Dave Barach4af9ba12017-06-07 15:18:23 -04001390 else if (num_wheels == 2)
Florin Corasadb5bd52018-06-22 15:29:38 -07001391 if (is_updates)
1392 return test2_double_updates (tm);
1393 else
1394 return test2_double (tm);
Dave Barach4af9ba12017-06-07 15:18:23 -04001395 else if (num_wheels == 3)
1396 {
1397 if (overflow == 0)
1398 return test2_triple (tm);
1399 else
1400 return test2_triple_ov (tm);
1401 }
Dave Barach8e8f98c2017-02-03 11:58:53 -05001402 }
Dave Barach4af9ba12017-06-07 15:18:23 -04001403 if (is_test3)
1404 return test3_triple_double (tm);
1405
1406 if (is_test4)
1407 return test4_double_double (tm);
1408
1409 if (is_test5)
1410 return test5_double (tm);
1411
Dave Barach8e8f98c2017-02-03 11:58:53 -05001412 /* NOTREACHED */
1413 return 0;
1414}
1415
1416#ifdef CLIB_UNIX
1417int
1418main (int argc, char *argv[])
1419{
1420 unformat_input_t i;
1421 clib_error_t *error;
1422 tw_timer_test_main_t *tm = &tw_timer_test_main;
1423
1424 clib_mem_init (0, 3ULL << 30);
1425
1426 unformat_init_command_line (&i, argv);
1427 error = timer_test_command_fn (tm, &i);
1428 unformat_free (&i);
1429
1430 if (error)
1431 {
1432 clib_error_report (error);
1433 return 1;
1434 }
1435 return 0;
1436}
1437#endif /* CLIB_UNIX */
1438
Dave Barach4af9ba12017-06-07 15:18:23 -04001439/* For debugging... */
1440int
1441pifi (void *p, u32 index)
1442{
1443 return pool_is_free_index (p, index);
1444}
1445
1446u32
1447vl (void *p)
1448{
1449 return vec_len (p);
1450}
1451
1452uword
1453pe (void *v)
1454{
1455 return (pool_elts (v));
1456}
1457
Dave Barach8e8f98c2017-02-03 11:58:53 -05001458/*
1459 * fd.io coding-style-patch-verification: ON
1460 *
1461 * Local Variables:
1462 * eval: (c-set-style "gnu")
1463 * End:
1464 */