blob: 47e5e49bf1ff27d762dde8564c10d169eee92073 [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);
319 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100320 pool_foreach (e, tm->test_elts)
321 {
Dave Barach8e8f98c2017-02-03 11:58:53 -0500322 tw_timer_stop_2t_1w_2048sl (&tm->single_wheel, e->stop_timer_handle);
323 vec_add1 (deleted_indices, e - tm->test_elts);
324 if (++j >= tm->ntimers / 4)
325 goto del_and_re_add;
Damjan Marionb2c31b62020-12-13 21:47:40 +0100326 }
Dave Barach8e8f98c2017-02-03 11:58:53 -0500327 /* *INDENT-ON* */
328
329 del_and_re_add:
330 for (j = 0; j < vec_len (deleted_indices); j++)
Dave Barach4af9ba12017-06-07 15:18:23 -0400331 {
332 pool_put_index (tm->test_elts, deleted_indices[j]);
333 }
Dave Barach8e8f98c2017-02-03 11:58:53 -0500334
335 deletes += j;
336
337 for (j = 0; j < tm->ntimers / 4; j++)
338 {
339 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400340 clib_memset (e, 0, sizeof (*e));
Dave Barach8e8f98c2017-02-03 11:58:53 -0500341
342 do
343 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400344 expiration_time = random_u64 (&tm->seed) & (2047);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500345 }
346 while (expiration_time == 0);
347
348 if (expiration_time > max_expiration_time)
349 max_expiration_time = expiration_time;
350
351 e->expected_to_expire =
352 expiration_time + tm->single_wheel.current_tick;
353 e->stop_timer_handle = tw_timer_start_2t_1w_2048sl
354 (&tm->single_wheel, e - tm->test_elts, 1 /* timer id */ ,
355 expiration_time);
356 }
357 adds += j;
358 }
359
360 vec_free (deleted_indices);
361
362 run_single_wheel (&tm->single_wheel, max_expiration_time + 1);
363
364 after = clib_time_now (&tm->clib_time);
365
366 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
367 tm->single_wheel.current_tick);
368 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
369 (after - before),
370 ((f64) adds + (f64) deletes +
371 (f64) tm->single_wheel.current_tick) / (after - before));
372
373 if (pool_elts (tm->test_elts))
374 fformat (stdout, "Note: %d elements remain in pool\n",
375 pool_elts (tm->test_elts));
376
377 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100378 pool_foreach (e, tm->test_elts)
379 {
Dave Barach8e8f98c2017-02-03 11:58:53 -0500380 fformat (stdout, "[%d] expected to expire %d\n",
381 e - tm->test_elts,
382 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100383 }
Dave Barach8e8f98c2017-02-03 11:58:53 -0500384 /* *INDENT-ON* */
385
386 pool_free (tm->test_elts);
387 tw_timer_wheel_free_2t_1w_2048sl (&tm->single_wheel);
388 return 0;
389}
390
391static clib_error_t *
392test2_double (tw_timer_test_main_t * tm)
393{
394 u32 i, j;
395 tw_timer_test_elt_t *e;
396 u32 initial_wheel_offset;
397 u32 expiration_time;
398 u32 max_expiration_time = 0;
399 u32 *deleted_indices = 0;
400 u32 adds = 0, deletes = 0;
401 f64 before, after;
402
403 clib_time_init (&tm->clib_time);
404
405 tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel,
406 expired_timer_double_callback,
Filip Tehlar816f4372017-04-26 16:09:06 +0200407 1.0 /* timer interval */ , ~0);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500408
409 /* Prime offset */
Dave Barach4af9ba12017-06-07 15:18:23 -0400410 initial_wheel_offset = 7577;
Dave Barach8e8f98c2017-02-03 11:58:53 -0500411
412 run_double_wheel (&tm->double_wheel, initial_wheel_offset);
413
Dave Barach4af9ba12017-06-07 15:18:23 -0400414 fformat (stdout, "initial wheel time %d, fast index %d slow index %d\n",
415 tm->double_wheel.current_tick,
416 tm->double_wheel.current_index[TW_TIMER_RING_FAST],
417 tm->double_wheel.current_index[TW_TIMER_RING_SLOW]);
418
419 initial_wheel_offset = tm->double_wheel.current_tick;
420
421 fformat (stdout,
422 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
Dave Barach8e8f98c2017-02-03 11:58:53 -0500423 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
424
425 before = clib_time_now (&tm->clib_time);
426
427 /* Prime the pump */
428 for (i = 0; i < tm->ntimers; i++)
429 {
430 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400431 clib_memset (e, 0, sizeof (*e));
Dave Barach8e8f98c2017-02-03 11:58:53 -0500432
433 do
434 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400435 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500436 }
437 while (expiration_time == 0);
438
439 if (expiration_time > max_expiration_time)
440 max_expiration_time = expiration_time;
441
442 e->expected_to_expire = expiration_time + initial_wheel_offset;
Dave Barach4af9ba12017-06-07 15:18:23 -0400443
Dave Barach8e8f98c2017-02-03 11:58:53 -0500444 e->stop_timer_handle =
445 tw_timer_start_16t_2w_512sl (&tm->double_wheel, e - tm->test_elts,
446 14 /* timer id */ ,
447 expiration_time);
448 }
449
450 adds += i;
451
452 for (i = 0; i < tm->niter; i++)
453 {
454 run_double_wheel (&tm->double_wheel, tm->ticks_per_iter);
455
456 j = 0;
457 vec_reset_length (deleted_indices);
458 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100459 pool_foreach (e, tm->test_elts)
460 {
Dave Barach8e8f98c2017-02-03 11:58:53 -0500461 tw_timer_stop_16t_2w_512sl (&tm->double_wheel, e->stop_timer_handle);
462 vec_add1 (deleted_indices, e - tm->test_elts);
463 if (++j >= tm->ntimers / 4)
464 goto del_and_re_add;
Damjan Marionb2c31b62020-12-13 21:47:40 +0100465 }
Dave Barach8e8f98c2017-02-03 11:58:53 -0500466 /* *INDENT-ON* */
467
468 del_and_re_add:
469 for (j = 0; j < vec_len (deleted_indices); j++)
470 pool_put_index (tm->test_elts, deleted_indices[j]);
471
472 deletes += j;
473
474 for (j = 0; j < tm->ntimers / 4; j++)
475 {
476 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400477 clib_memset (e, 0, sizeof (*e));
Dave Barach8e8f98c2017-02-03 11:58:53 -0500478
479 do
480 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400481 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500482 }
483 while (expiration_time == 0);
484
485 if (expiration_time > max_expiration_time)
486 max_expiration_time = expiration_time;
487
488 e->expected_to_expire = expiration_time +
489 tm->double_wheel.current_tick;
Dave Barach4af9ba12017-06-07 15:18:23 -0400490
Dave Barach8e8f98c2017-02-03 11:58:53 -0500491 e->stop_timer_handle = tw_timer_start_16t_2w_512sl
492 (&tm->double_wheel, e - tm->test_elts, 14 /* timer id */ ,
493 expiration_time);
494 }
495 adds += j;
496 }
497
498 vec_free (deleted_indices);
499
500 run_double_wheel (&tm->double_wheel, max_expiration_time + 1);
501
502 after = clib_time_now (&tm->clib_time);
503
504 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
505 tm->double_wheel.current_tick);
506 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
507 (after - before),
508 ((f64) adds + (f64) deletes +
509 (f64) tm->double_wheel.current_tick) / (after - before));
510
511 if (pool_elts (tm->test_elts))
512 fformat (stdout, "Note: %d elements remain in pool\n",
513 pool_elts (tm->test_elts));
514
515 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100516 pool_foreach (e, tm->test_elts)
517 {
Dave Barach8e8f98c2017-02-03 11:58:53 -0500518 fformat (stdout, "[%d] expected to expire %d\n",
519 e - tm->test_elts,
520 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100521 }
Dave Barach8e8f98c2017-02-03 11:58:53 -0500522 /* *INDENT-ON* */
523
524 pool_free (tm->test_elts);
525 tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel);
526 return 0;
527}
528
Florin Corasadb5bd52018-06-22 15:29:38 -0700529static u32
530get_expiration_time (tw_timer_test_main_t * tm)
531{
532 u32 expiration_time;
533 do
534 {
535 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
536 }
537 while (expiration_time == 0);
538 return expiration_time;
539}
540
541static clib_error_t *
542test2_double_updates (tw_timer_test_main_t * tm)
543{
544 u32 i, j;
545 tw_timer_test_elt_t *e;
546 u32 initial_wheel_offset;
547 u32 expiration_time;
548 u32 max_expiration_time = 0, updates = 0;
549 f64 before, after;
550
551 clib_time_init (&tm->clib_time);
552 tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel,
553 expired_timer_double_callback,
554 1.0 /* timer interval */ , ~0);
555
556 /* Prime offset */
557 initial_wheel_offset = 7577;
558 run_double_wheel (&tm->double_wheel, initial_wheel_offset);
559 fformat (stdout, "initial wheel time %d, fast index %d slow index %d\n",
560 tm->double_wheel.current_tick,
561 tm->double_wheel.current_index[TW_TIMER_RING_FAST],
562 tm->double_wheel.current_index[TW_TIMER_RING_SLOW]);
563
564 initial_wheel_offset = tm->double_wheel.current_tick;
565 fformat (stdout,
566 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
567 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
568
569 before = clib_time_now (&tm->clib_time);
570
571 /* Prime the pump */
572 for (i = 0; i < tm->ntimers; i++)
573 {
574 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400575 clib_memset (e, 0, sizeof (*e));
Florin Corasadb5bd52018-06-22 15:29:38 -0700576
577 expiration_time = get_expiration_time (tm);
578 max_expiration_time = clib_max (expiration_time, max_expiration_time);
579
580 e->expected_to_expire = expiration_time + initial_wheel_offset;
581 e->stop_timer_handle = tw_timer_start_16t_2w_512sl (&tm->double_wheel,
582 e - tm->test_elts,
583 14 /* timer id */ ,
584 expiration_time);
585 }
586
587 for (i = 0; i < tm->niter; i++)
588 {
589 run_double_wheel (&tm->double_wheel, tm->ticks_per_iter);
590
591 j = 0;
592
593 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100594 pool_foreach (e, tm->test_elts)
595 {
Florin Corasadb5bd52018-06-22 15:29:38 -0700596 expiration_time = get_expiration_time (tm);
597 max_expiration_time = clib_max (expiration_time, max_expiration_time);
598 e->expected_to_expire = expiration_time
599 + tm->double_wheel.current_tick;
600 tw_timer_update_16t_2w_512sl (&tm->double_wheel, e->stop_timer_handle,
601 expiration_time);
602 if (++j >= tm->ntimers / 4)
603 goto done;
Damjan Marionb2c31b62020-12-13 21:47:40 +0100604 }
Florin Corasadb5bd52018-06-22 15:29:38 -0700605 /* *INDENT-ON* */
606
607 done:
608 updates += j;
609 }
610
611 run_double_wheel (&tm->double_wheel, max_expiration_time + 1);
612
613 after = clib_time_now (&tm->clib_time);
614
615 fformat (stdout, "%d updates, %d ticks\n", updates,
616 tm->double_wheel.current_tick);
617 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
618 (after - before),
619 ((f64) updates + (f64) tm->double_wheel.current_tick) / (after -
620 before));
621
622 if (pool_elts (tm->test_elts))
623 fformat (stdout, "Note: %d elements remain in pool\n",
624 pool_elts (tm->test_elts));
625
626 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100627 pool_foreach (e, tm->test_elts)
628 {
Florin Corasadb5bd52018-06-22 15:29:38 -0700629 fformat (stdout, "[%d] expected to expire %d\n",
630 e - tm->test_elts,
631 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100632 }
Florin Corasadb5bd52018-06-22 15:29:38 -0700633 /* *INDENT-ON* */
634
635 pool_free (tm->test_elts);
636 tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel);
637 return 0;
638}
639
Dave Barach8e8f98c2017-02-03 11:58:53 -0500640static clib_error_t *
Dave Barach4af9ba12017-06-07 15:18:23 -0400641test2_triple (tw_timer_test_main_t * tm)
642{
643 u32 i, j;
644 tw_timer_test_elt_t *e;
645 u32 initial_wheel_offset = 0;
646 u32 expiration_time;
647 u32 max_expiration_time = 0;
648 u32 *deleted_indices = 0;
649 u32 adds = 0, deletes = 0;
650 f64 before, after;
651
652 clib_time_init (&tm->clib_time);
653
654 tw_timer_wheel_init_4t_3w_256sl (&tm->triple_wheel,
655 expired_timer_triple_callback,
656 1.0 /* timer interval */ , ~0);
657
658
659 /* Prime offset */
660 initial_wheel_offset = 75700;
661 run_triple_wheel (&tm->triple_wheel, initial_wheel_offset);
662
663 fformat (stdout,
664 "initial wheel time %d, fi %d si %d gi %d\n",
665 tm->triple_wheel.current_tick,
666 tm->triple_wheel.current_index[TW_TIMER_RING_FAST],
667 tm->triple_wheel.current_index[TW_TIMER_RING_SLOW],
668 tm->triple_wheel.current_index[TW_TIMER_RING_GLACIER]);
669
670 initial_wheel_offset = tm->triple_wheel.current_tick;
671
672 fformat (stdout,
673 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
674 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
675
676 before = clib_time_now (&tm->clib_time);
677
678 /* Prime the pump */
679 for (i = 0; i < tm->ntimers; i++)
680 {
681 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400682 clib_memset (e, 0, sizeof (*e));
Dave Barach4af9ba12017-06-07 15:18:23 -0400683
684 do
685 {
686 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
687 }
688 while (expiration_time == 0);
689
690 if (expiration_time > max_expiration_time)
691 max_expiration_time = expiration_time;
692
693 e->expected_to_expire = expiration_time + initial_wheel_offset;
694
695 e->stop_timer_handle =
696 tw_timer_start_4t_3w_256sl (&tm->triple_wheel, e - tm->test_elts,
697 3 /* timer id */ ,
698 expiration_time);
699 }
700
701 adds += i;
702
703 for (i = 0; i < tm->niter; i++)
704 {
705 run_triple_wheel (&tm->triple_wheel, tm->ticks_per_iter);
706
707 j = 0;
708 vec_reset_length (deleted_indices);
709 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100710 pool_foreach (e, tm->test_elts)
711 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400712 tw_timer_stop_4t_3w_256sl (&tm->triple_wheel, e->stop_timer_handle);
713 vec_add1 (deleted_indices, e - tm->test_elts);
714 if (++j >= tm->ntimers / 4)
715 goto del_and_re_add;
Damjan Marionb2c31b62020-12-13 21:47:40 +0100716 }
Dave Barach4af9ba12017-06-07 15:18:23 -0400717 /* *INDENT-ON* */
718
719 del_and_re_add:
720 for (j = 0; j < vec_len (deleted_indices); j++)
721 pool_put_index (tm->test_elts, deleted_indices[j]);
722
723 deletes += j;
724
725 for (j = 0; j < tm->ntimers / 4; j++)
726 {
727 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400728 clib_memset (e, 0, sizeof (*e));
Dave Barach4af9ba12017-06-07 15:18:23 -0400729
730 do
731 {
732 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
733 }
734 while (expiration_time == 0);
735
736 if (expiration_time > max_expiration_time)
737 max_expiration_time = expiration_time;
738
739 e->expected_to_expire = expiration_time +
740 tm->triple_wheel.current_tick;
741
742 e->stop_timer_handle = tw_timer_start_4t_3w_256sl
743 (&tm->triple_wheel, e - tm->test_elts, 3 /* timer id */ ,
744 expiration_time);
745 }
746 adds += j;
747 }
748
749 vec_free (deleted_indices);
750
751 run_triple_wheel (&tm->triple_wheel, max_expiration_time + 1);
752
753 after = clib_time_now (&tm->clib_time);
754
755 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
756 tm->triple_wheel.current_tick);
757 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
758 (after - before),
759 ((f64) adds + (f64) deletes +
760 (f64) tm->triple_wheel.current_tick) / (after - before));
761
762 if (pool_elts (tm->test_elts))
763 fformat (stdout, "Note: %d elements remain in pool\n",
764 pool_elts (tm->test_elts));
765
766 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100767 pool_foreach (e, tm->test_elts)
768 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400769 fformat (stdout, "[%d] expected to expire %d\n",
770 e - tm->test_elts,
771 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100772 }
Dave Barach4af9ba12017-06-07 15:18:23 -0400773 /* *INDENT-ON* */
774
775 pool_free (tm->test_elts);
776 tw_timer_wheel_free_4t_3w_256sl (&tm->triple_wheel);
777 return 0;
778}
779
780static clib_error_t *
781test2_triple_ov (tw_timer_test_main_t * tm)
782{
783 u32 i, j;
784 tw_timer_test_elt_t *e;
785 u32 initial_wheel_offset = 0;
786 u32 expiration_time;
787 u32 max_expiration_time = 0;
788 u32 *deleted_indices = 0;
789 u32 adds = 0, deletes = 0;
790 f64 before, after;
791
792 clib_time_init (&tm->clib_time);
793
794 tw_timer_wheel_init_1t_3w_1024sl_ov (&tm->triple_ov_wheel,
795 expired_timer_triple_ov_callback,
796 1.0 /* timer interval */ , ~0);
797
798
799 /* Prime offset */
800 initial_wheel_offset = 75700;
801 run_triple_ov_wheel (&tm->triple_ov_wheel, initial_wheel_offset);
802
803 fformat (stdout,
804 "initial wheel time %d, fi %d si %d gi %d\n",
805 tm->triple_ov_wheel.current_tick,
806 tm->triple_ov_wheel.current_index[TW_TIMER_RING_FAST],
807 tm->triple_ov_wheel.current_index[TW_TIMER_RING_SLOW],
808 tm->triple_ov_wheel.current_index[TW_TIMER_RING_GLACIER]);
809
810 initial_wheel_offset = tm->triple_ov_wheel.current_tick;
811
812 fformat (stdout,
813 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
814 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
815
816 before = clib_time_now (&tm->clib_time);
817
818 /* Prime the pump */
819 for (i = 0; i < tm->ntimers; i++)
820 {
821 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400822 clib_memset (e, 0, sizeof (*e));
Dave Barach4af9ba12017-06-07 15:18:23 -0400823
824 do
825 {
826 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
827 }
828 while (expiration_time == 0);
829
830 if (expiration_time > max_expiration_time)
831 max_expiration_time = expiration_time;
832
833 e->expected_to_expire = expiration_time + initial_wheel_offset;
834
835 e->stop_timer_handle =
836 tw_timer_start_1t_3w_1024sl_ov (&tm->triple_ov_wheel,
837 e - tm->test_elts, 0 /* timer id */ ,
838 expiration_time);
839 }
840
841 adds += i;
842
843 for (i = 0; i < tm->niter; i++)
844 {
845 run_triple_ov_wheel (&tm->triple_ov_wheel, tm->ticks_per_iter);
846
847 j = 0;
848 vec_reset_length (deleted_indices);
849 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100850 pool_foreach (e, tm->test_elts)
851 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400852 tw_timer_stop_1t_3w_1024sl_ov (&tm->triple_ov_wheel,
853 e->stop_timer_handle);
854 vec_add1 (deleted_indices, e - tm->test_elts);
855 if (++j >= tm->ntimers / 4)
856 goto del_and_re_add;
Damjan Marionb2c31b62020-12-13 21:47:40 +0100857 }
Dave Barach4af9ba12017-06-07 15:18:23 -0400858 /* *INDENT-ON* */
859
860 del_and_re_add:
861 for (j = 0; j < vec_len (deleted_indices); j++)
862 pool_put_index (tm->test_elts, deleted_indices[j]);
863
864 deletes += j;
865
866 for (j = 0; j < tm->ntimers / 4; j++)
867 {
868 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400869 clib_memset (e, 0, sizeof (*e));
Dave Barach4af9ba12017-06-07 15:18:23 -0400870
871 do
872 {
873 expiration_time = random_u64 (&tm->seed) & ((1 << 17) - 1);
874 }
875 while (expiration_time == 0);
876
877 if (expiration_time > max_expiration_time)
878 max_expiration_time = expiration_time;
879
880 e->expected_to_expire = expiration_time +
881 tm->triple_ov_wheel.current_tick;
882
883 e->stop_timer_handle = tw_timer_start_1t_3w_1024sl_ov
884 (&tm->triple_ov_wheel, e - tm->test_elts, 0 /* timer id */ ,
885 expiration_time);
886 }
887 adds += j;
888 }
889
890 vec_free (deleted_indices);
891
892 run_triple_ov_wheel (&tm->triple_ov_wheel, max_expiration_time + 1);
893
894 after = clib_time_now (&tm->clib_time);
895
896 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
897 tm->triple_ov_wheel.current_tick);
898 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
899 (after - before),
900 ((f64) adds + (f64) deletes +
901 (f64) tm->triple_ov_wheel.current_tick) / (after - before));
902
903 if (pool_elts (tm->test_elts))
904 fformat (stdout, "Note: %d elements remain in pool\n",
905 pool_elts (tm->test_elts));
906
907 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100908 pool_foreach (e, tm->test_elts)
909 {
Dave Barach4af9ba12017-06-07 15:18:23 -0400910 TWT (tw_timer) * t;
911
912 fformat (stdout, "[%d] expected to expire %d\n",
913 e - tm->test_elts,
914 e->expected_to_expire);
915 t = pool_elt_at_index (tm->triple_ov_wheel.timers, e->stop_timer_handle);
916 fformat (stdout, " expiration_time %lld\n", t->expiration_time);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100917 }
Dave Barach4af9ba12017-06-07 15:18:23 -0400918 /* *INDENT-ON* */
919
920 pool_free (tm->test_elts);
921 tw_timer_wheel_free_1t_3w_1024sl_ov (&tm->triple_ov_wheel);
922 return 0;
923}
924
925static clib_error_t *
Dave Barach8e8f98c2017-02-03 11:58:53 -0500926test1_single (tw_timer_test_main_t * tm)
927{
928 u32 i;
929 tw_timer_test_elt_t *e;
930 u32 offset;
931
932 tw_timer_wheel_init_2t_1w_2048sl (&tm->single_wheel,
933 expired_timer_single_callback,
Filip Tehlar816f4372017-04-26 16:09:06 +0200934 1.0 /* timer interval */ , ~0);
Dave Barach8e8f98c2017-02-03 11:58:53 -0500935
936 /*
937 * Prime offset, to make sure that the wheel starts in a
938 * non-trivial position
939 */
940 offset = 123;
941
942 run_single_wheel (&tm->single_wheel, offset);
943
944 fformat (stdout, "initial wheel time %d, fast index %d\n",
945 tm->single_wheel.current_tick,
946 tm->single_wheel.current_index[TW_TIMER_RING_FAST]);
947
Dave Barach4af9ba12017-06-07 15:18:23 -0400948 offset = tm->single_wheel.current_tick;
949
Dave Barach8e8f98c2017-02-03 11:58:53 -0500950 for (i = 0; i < tm->ntimers; i++)
951 {
952 u32 expected_to_expire;
953 u32 timer_arg;
954
955 timer_arg = 1 + i;
956 timer_arg &= 2047;
957 if (timer_arg == 0)
958 timer_arg = 1;
959
Dave Barach90767892020-04-01 14:34:39 -0400960 expected_to_expire = timer_arg + tm->single_wheel.current_tick;
Dave Barach8e8f98c2017-02-03 11:58:53 -0500961
962 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -0400963 clib_memset (e, 0, sizeof (*e));
Dave Barach8e8f98c2017-02-03 11:58:53 -0500964 e->expected_to_expire = expected_to_expire;
965 e->stop_timer_handle = tw_timer_start_2t_1w_2048sl
966 (&tm->single_wheel, e - tm->test_elts, 1 /* timer id */ ,
967 timer_arg);
968 }
969 run_single_wheel (&tm->single_wheel, tm->ntimers + 3);
970
971 if (pool_elts (tm->test_elts))
972 fformat (stdout, "Note: %d elements remain in pool\n",
973 pool_elts (tm->test_elts));
974
975 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100976 pool_foreach (e, tm->test_elts)
977 {
Dave Barach8e8f98c2017-02-03 11:58:53 -0500978 fformat(stdout, "[%d] expected to expire %d\n",
979 e - tm->test_elts,
980 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100981 }
Dave Barach8e8f98c2017-02-03 11:58:53 -0500982 /* *INDENT-ON* */
983
984 fformat (stdout,
985 "final wheel time %d, fast index %d\n",
986 tm->single_wheel.current_tick,
987 tm->single_wheel.current_index[TW_TIMER_RING_FAST]);
988
989 pool_free (tm->test_elts);
990 tw_timer_wheel_free_2t_1w_2048sl (&tm->single_wheel);
991 return 0;
992}
993
994static clib_error_t *
995test1_double (tw_timer_test_main_t * tm)
996{
997 u32 i;
998 tw_timer_test_elt_t *e;
999 u32 offset;
1000
1001 tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel,
1002 expired_timer_double_callback,
Filip Tehlar816f4372017-04-26 16:09:06 +02001003 1.0 /* timer interval */ , ~0);
Dave Barach8e8f98c2017-02-03 11:58:53 -05001004
1005 /*
1006 * Prime offset, to make sure that the wheel starts in a
1007 * non-trivial position
1008 */
1009 offset = 227989;
1010
1011 run_double_wheel (&tm->double_wheel, offset);
1012
1013 fformat (stdout, "initial wheel time %d, fast index %d\n",
1014 tm->double_wheel.current_tick,
1015 tm->double_wheel.current_index[TW_TIMER_RING_FAST]);
1016
1017 for (i = 0; i < tm->ntimers; i++)
1018 {
1019 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -04001020 clib_memset (e, 0, sizeof (*e));
Dave Barach8e8f98c2017-02-03 11:58:53 -05001021
Dave Barach90767892020-04-01 14:34:39 -04001022 e->expected_to_expire = i + tm->double_wheel.current_tick + 1;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001023 e->stop_timer_handle = tw_timer_start_16t_2w_512sl
1024 (&tm->double_wheel, e - tm->test_elts, 14 /* timer id */ ,
1025 i + 1);
1026 }
1027 run_double_wheel (&tm->double_wheel, tm->ntimers + 3);
1028
1029 if (pool_elts (tm->test_elts))
1030 fformat (stdout, "Note: %d elements remain in pool\n",
1031 pool_elts (tm->test_elts));
1032
1033 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +01001034 pool_foreach (e, tm->test_elts)
1035 {
Dave Barach8e8f98c2017-02-03 11:58:53 -05001036 fformat(stdout, "[%d] expected to expire %d\n",
1037 e - tm->test_elts,
1038 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +01001039 }
Dave Barach8e8f98c2017-02-03 11:58:53 -05001040 /* *INDENT-ON* */
1041
1042 fformat (stdout,
1043 "final wheel time %d, fast index %d\n",
1044 tm->double_wheel.current_tick,
1045 tm->double_wheel.current_index[TW_TIMER_RING_FAST]);
1046
1047 pool_free (tm->test_elts);
1048 tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel);
1049 return 0;
1050}
1051
1052static clib_error_t *
Dave Barach90767892020-04-01 14:34:39 -04001053test1_two_timer_double (tw_timer_test_main_t * tm)
1054{
1055 u32 i;
1056 tw_timer_test_elt_t *e;
1057 u32 offset;
1058
1059 tw_timer_wheel_init_2t_2w_512sl (&tm->two_timer_double_wheel,
1060 expired_timer_two_timer_double_callback,
1061 1.0 /* timer interval */ , ~0);
1062
1063 /*
1064 * Prime offset, to make sure that the wheel starts in a
1065 * non-trivial position
1066 */
1067 offset = 2745;
1068
1069 run_two_timer_double_wheel (&tm->two_timer_double_wheel, offset);
1070
1071 fformat (stdout, "initial wheel time %d, fast index %d\n",
1072 tm->two_timer_double_wheel.current_tick,
1073 tm->two_timer_double_wheel.current_index[TW_TIMER_RING_FAST]);
1074
1075 for (i = 0; i < tm->ntimers; i++)
1076 {
1077 pool_get (tm->test_elts, e);
1078 clib_memset (e, 0, sizeof (*e));
1079
1080 e->expected_to_expire = i + tm->two_timer_double_wheel.current_tick + 1;
1081 e->stop_timer_handle = tw_timer_start_2t_2w_512sl
1082 (&tm->two_timer_double_wheel, e - tm->test_elts, 1 /* timer id */ ,
1083 i + 1);
1084 }
1085 run_two_timer_double_wheel (&tm->two_timer_double_wheel, tm->ntimers + 3);
1086
1087 if (pool_elts (tm->test_elts))
1088 fformat (stdout, "Note: %d elements remain in pool\n",
1089 pool_elts (tm->test_elts));
1090
1091 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +01001092 pool_foreach (e, tm->test_elts)
1093 {
Dave Barach90767892020-04-01 14:34:39 -04001094 fformat(stdout, "[%d] expected to expire %d\n",
1095 e - tm->test_elts,
1096 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +01001097 }
Dave Barach90767892020-04-01 14:34:39 -04001098 /* *INDENT-ON* */
1099
1100 fformat (stdout,
1101 "final wheel time %d, fast index %d\n",
1102 tm->two_timer_double_wheel.current_tick,
1103 tm->two_timer_double_wheel.current_index[TW_TIMER_RING_FAST]);
1104
1105 pool_free (tm->test_elts);
1106 tw_timer_wheel_free_2t_2w_512sl (&tm->two_timer_double_wheel);
1107 return 0;
1108}
1109
1110static clib_error_t *
Dave Barach4af9ba12017-06-07 15:18:23 -04001111test3_triple_double (tw_timer_test_main_t * tm)
1112{
1113 tw_timer_test_elt_t *e;
1114 u32 initial_wheel_offset = 0;
1115 u32 expiration_time;
1116 u32 max_expiration_time = 0;
1117 u32 adds = 0, deletes = 0;
1118 f64 before, after;
1119
1120 clib_time_init (&tm->clib_time);
1121
1122 tw_timer_wheel_init_4t_3w_256sl (&tm->triple_wheel,
1123 expired_timer_triple_callback,
1124 1.0 /* timer interval */ , ~0);
1125
1126 initial_wheel_offset = 0;
1127 run_triple_wheel (&tm->triple_wheel, initial_wheel_offset);
1128
1129 fformat (stdout,
1130 "initial wheel time %d, fi %d si %d gi %d\n",
1131 tm->triple_wheel.current_tick,
1132 tm->triple_wheel.current_index[TW_TIMER_RING_FAST],
1133 tm->triple_wheel.current_index[TW_TIMER_RING_SLOW],
1134 tm->triple_wheel.current_index[TW_TIMER_RING_GLACIER]);
1135
1136 initial_wheel_offset = tm->triple_wheel.current_tick;
1137
1138 fformat (stdout, "Create a timer which expires at wheel-time (1, 0, 0)\n");
1139
1140 before = clib_time_now (&tm->clib_time);
1141
1142 /* Prime the pump */
1143 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -04001144 clib_memset (e, 0, sizeof (*e));
Dave Barach4af9ba12017-06-07 15:18:23 -04001145
1146 /* 1 glacier ring tick from now */
1147 expiration_time = TW_SLOTS_PER_RING * TW_SLOTS_PER_RING;
1148 e->expected_to_expire = expiration_time + initial_wheel_offset;
1149 max_expiration_time = expiration_time;
1150
1151 e->stop_timer_handle =
1152 tw_timer_start_4t_3w_256sl (&tm->triple_wheel, e - tm->test_elts,
1153 3 /* timer id */ ,
1154 expiration_time);
1155
1156 run_triple_wheel (&tm->triple_wheel, max_expiration_time + 1);
1157
1158 after = clib_time_now (&tm->clib_time);
1159
1160 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
1161 tm->triple_wheel.current_tick);
1162 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
1163 (after - before),
1164 ((f64) adds + (f64) deletes +
1165 (f64) tm->triple_wheel.current_tick) / (after - before));
1166
1167 if (pool_elts (tm->test_elts))
1168 fformat (stdout, "Note: %d elements remain in pool\n",
1169 pool_elts (tm->test_elts));
1170
1171 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +01001172 pool_foreach (e, tm->test_elts)
1173 {
Dave Barach4af9ba12017-06-07 15:18:23 -04001174 fformat (stdout, "[%d] expected to expire %d\n",
1175 e - tm->test_elts,
1176 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +01001177 }
Dave Barach4af9ba12017-06-07 15:18:23 -04001178 /* *INDENT-ON* */
1179
1180 pool_free (tm->test_elts);
1181 tw_timer_wheel_free_4t_3w_256sl (&tm->triple_wheel);
1182 return 0;
1183}
1184
1185static clib_error_t *
1186test4_double_double (tw_timer_test_main_t * tm)
1187{
1188 u32 i;
1189 tw_timer_test_elt_t *e;
1190 u32 initial_wheel_offset;
1191 u32 expiration_time;
1192 u32 max_expiration_time = 0;
1193 u32 *deleted_indices = 0;
1194 u32 adds = 0, deletes = 0;
1195 f64 before, after;
1196
1197 clib_time_init (&tm->clib_time);
1198
1199 tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel,
1200 expired_timer_double_callback,
1201 1.0 /* timer interval */ , ~0);
1202 /* Prime offset */
1203 initial_wheel_offset = 0;
1204
1205 run_double_wheel (&tm->double_wheel, initial_wheel_offset);
1206
1207 fformat (stdout, "initial wheel time %d, fast index %d slow index %d\n",
1208 tm->double_wheel.current_tick,
1209 tm->double_wheel.current_index[TW_TIMER_RING_FAST],
1210 tm->double_wheel.current_index[TW_TIMER_RING_SLOW]);
1211
1212 initial_wheel_offset = tm->double_wheel.current_tick;
1213
1214 fformat (stdout, "test timer which expires at 512 ticks\n");
1215
1216 before = clib_time_now (&tm->clib_time);
1217
1218 /* Prime the pump */
1219 for (i = 0; i < tm->ntimers; i++)
1220 {
1221 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -04001222 clib_memset (e, 0, sizeof (*e));
Dave Barach4af9ba12017-06-07 15:18:23 -04001223
1224 expiration_time = 512;
1225
1226 if (expiration_time > max_expiration_time)
1227 max_expiration_time = expiration_time;
1228
1229 e->expected_to_expire = expiration_time + initial_wheel_offset;
1230 e->stop_timer_handle =
1231 tw_timer_start_16t_2w_512sl (&tm->double_wheel, e - tm->test_elts,
1232 14 /* timer id */ ,
1233 expiration_time);
1234 }
1235
1236 adds = 1;
1237
1238 vec_free (deleted_indices);
1239
1240 run_double_wheel (&tm->double_wheel, max_expiration_time + 1);
1241
1242 after = clib_time_now (&tm->clib_time);
1243
1244 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
1245 tm->double_wheel.current_tick);
1246 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
1247 (after - before),
1248 ((f64) adds + (f64) deletes +
1249 (f64) tm->double_wheel.current_tick) / (after - before));
1250
1251 if (pool_elts (tm->test_elts))
1252 fformat (stdout, "Note: %d elements remain in pool\n",
1253 pool_elts (tm->test_elts));
1254
1255 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +01001256 pool_foreach (e, tm->test_elts)
1257 {
Dave Barach4af9ba12017-06-07 15:18:23 -04001258 fformat (stdout, "[%d] expected to expire %d\n",
1259 e - tm->test_elts,
1260 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +01001261 }
Dave Barach4af9ba12017-06-07 15:18:23 -04001262 /* *INDENT-ON* */
1263
1264 pool_free (tm->test_elts);
1265 tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel);
1266 return 0;
1267}
1268
1269static clib_error_t *
1270test5_double (tw_timer_test_main_t * tm)
1271{
1272 u32 i;
1273 tw_timer_test_elt_t *e;
1274 u32 initial_wheel_offset;
1275 u32 expiration_time;
1276 u32 max_expiration_time = 0;
1277 u32 adds = 0, deletes = 0;
1278 f64 before, after;
1279
1280 clib_time_init (&tm->clib_time);
1281
1282 tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel,
1283 expired_timer_double_callback,
1284 1.0 /* timer interval */ , ~0);
1285
1286 /* Prime offset */
1287 initial_wheel_offset = 7567;
1288
1289 run_double_wheel (&tm->double_wheel, initial_wheel_offset);
1290
1291 fformat (stdout, "initial wheel time %d, fast index %d slow index %d\n",
1292 tm->double_wheel.current_tick,
1293 tm->double_wheel.current_index[TW_TIMER_RING_FAST],
1294 tm->double_wheel.current_index[TW_TIMER_RING_SLOW]);
1295
1296 initial_wheel_offset = tm->double_wheel.current_tick;
1297
1298 fformat (stdout,
1299 "test %d timers, %d iter, %d ticks per iter, 0x%llx seed\n",
1300 tm->ntimers, tm->niter, tm->ticks_per_iter, tm->seed);
1301
1302 before = clib_time_now (&tm->clib_time);
1303
1304 /* Prime the pump */
1305 for (i = 0; i < tm->ntimers; i++)
1306 {
1307 pool_get (tm->test_elts, e);
Dave Barachb7b92992018-10-17 10:38:51 -04001308 clib_memset (e, 0, sizeof (*e));
Dave Barach4af9ba12017-06-07 15:18:23 -04001309
1310 expiration_time = i + 1;
1311
1312 if (expiration_time > max_expiration_time)
1313 max_expiration_time = expiration_time;
1314
1315 e->expected_to_expire = expiration_time + initial_wheel_offset;
1316 e->stop_timer_handle =
1317 tw_timer_start_16t_2w_512sl (&tm->double_wheel, e - tm->test_elts,
1318 14 /* timer id */ ,
1319 expiration_time);
1320 }
1321
1322 adds += i;
1323
1324 run_double_wheel (&tm->double_wheel, max_expiration_time + 1);
1325
1326 after = clib_time_now (&tm->clib_time);
1327
1328 fformat (stdout, "%d adds, %d deletes, %d ticks\n", adds, deletes,
1329 tm->double_wheel.current_tick);
1330 fformat (stdout, "test ran %.2f seconds, %.2f ops/second\n",
1331 (after - before),
1332 ((f64) adds + (f64) deletes +
1333 (f64) tm->double_wheel.current_tick) / (after - before));
1334
1335 if (pool_elts (tm->test_elts))
1336 fformat (stdout, "Note: %d elements remain in pool\n",
1337 pool_elts (tm->test_elts));
1338
1339 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +01001340 pool_foreach (e, tm->test_elts)
1341 {
Dave Barach4af9ba12017-06-07 15:18:23 -04001342 fformat (stdout, "[%d] expected to expire %d\n",
1343 e - tm->test_elts,
1344 e->expected_to_expire);
Damjan Marionb2c31b62020-12-13 21:47:40 +01001345 }
Dave Barach4af9ba12017-06-07 15:18:23 -04001346 /* *INDENT-ON* */
1347
1348 pool_free (tm->test_elts);
1349 tw_timer_wheel_free_16t_2w_512sl (&tm->double_wheel);
1350 return 0;
1351}
1352
1353static clib_error_t *
Dave Barach8e8f98c2017-02-03 11:58:53 -05001354timer_test_command_fn (tw_timer_test_main_t * tm, unformat_input_t * input)
1355{
1356
Florin Corasadb5bd52018-06-22 15:29:38 -07001357 int is_test1 = 0, is_updates = 0;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001358 int num_wheels = 1;
1359 int is_test2 = 0;
Dave Barach4af9ba12017-06-07 15:18:23 -04001360 int is_test3 = 0;
1361 int is_test4 = 0;
1362 int is_test5 = 0;
1363 int overflow = 0;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001364
Dave Barachb7b92992018-10-17 10:38:51 -04001365 clib_memset (tm, 0, sizeof (*tm));
Dave Barach8e8f98c2017-02-03 11:58:53 -05001366 /* Default values */
1367 tm->ntimers = 100000;
Dave Barach4af9ba12017-06-07 15:18:23 -04001368 tm->seed = 0xDEADDABEB00BFACE;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001369 tm->niter = 1000;
1370 tm->ticks_per_iter = 727;
1371
1372 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1373 {
Dave Barach4af9ba12017-06-07 15:18:23 -04001374 if (unformat (input, "seed %lld", &tm->seed))
Dave Barach8e8f98c2017-02-03 11:58:53 -05001375 ;
1376 else if (unformat (input, "test1"))
1377 is_test1 = 1;
1378 else if (unformat (input, "test2"))
1379 is_test2 = 1;
Dave Barach4af9ba12017-06-07 15:18:23 -04001380 else if (unformat (input, "overflow"))
1381 overflow = 1;
1382 else if (unformat (input, "lebron"))
1383 is_test3 = 1;
1384 else if (unformat (input, "wilt"))
1385 is_test4 = 1;
1386 else if (unformat (input, "linear"))
1387 is_test5 = 1;
Florin Corasadb5bd52018-06-22 15:29:38 -07001388 else if (unformat (input, "updates"))
1389 is_updates = 1;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001390 else if (unformat (input, "wheels %d", &num_wheels))
1391 ;
1392 else if (unformat (input, "ntimers %d", &tm->ntimers))
1393 ;
1394 else if (unformat (input, "niter %d", &tm->niter))
1395 ;
1396 else if (unformat (input, "ticks_per_iter %d", &tm->ticks_per_iter))
1397 ;
Dave Barach4af9ba12017-06-07 15:18:23 -04001398 else
1399 break;
Dave Barach8e8f98c2017-02-03 11:58:53 -05001400 }
1401
Dave Barach4af9ba12017-06-07 15:18:23 -04001402 if (is_test1 + is_test2 + is_test3 + is_test4 + is_test5 == 0)
Dave Barach8e8f98c2017-02-03 11:58:53 -05001403 return clib_error_return (0, "No test specified [test1..n]");
1404
Dave Barach4af9ba12017-06-07 15:18:23 -04001405 if (num_wheels < 1 || num_wheels > 3)
Dave Barach8e8f98c2017-02-03 11:58:53 -05001406 return clib_error_return (0, "unsupported... 1 or 2 wheels only");
1407
1408 if (is_test1)
1409 {
1410 if (num_wheels == 1)
1411 return test1_single (tm);
1412 else
Dave Barach90767892020-04-01 14:34:39 -04001413 {
1414 (void) test1_double (tm);
1415 return test1_two_timer_double (tm);
1416 }
Dave Barach8e8f98c2017-02-03 11:58:53 -05001417 }
1418 if (is_test2)
1419 {
1420 if (num_wheels == 1)
1421 return test2_single (tm);
Dave Barach4af9ba12017-06-07 15:18:23 -04001422 else if (num_wheels == 2)
Florin Corasadb5bd52018-06-22 15:29:38 -07001423 if (is_updates)
1424 return test2_double_updates (tm);
1425 else
1426 return test2_double (tm);
Dave Barach4af9ba12017-06-07 15:18:23 -04001427 else if (num_wheels == 3)
1428 {
1429 if (overflow == 0)
1430 return test2_triple (tm);
1431 else
1432 return test2_triple_ov (tm);
1433 }
Dave Barach8e8f98c2017-02-03 11:58:53 -05001434 }
Dave Barach4af9ba12017-06-07 15:18:23 -04001435 if (is_test3)
1436 return test3_triple_double (tm);
1437
1438 if (is_test4)
1439 return test4_double_double (tm);
1440
1441 if (is_test5)
1442 return test5_double (tm);
1443
Dave Barach8e8f98c2017-02-03 11:58:53 -05001444 /* NOTREACHED */
1445 return 0;
1446}
1447
1448#ifdef CLIB_UNIX
1449int
1450main (int argc, char *argv[])
1451{
1452 unformat_input_t i;
1453 clib_error_t *error;
1454 tw_timer_test_main_t *tm = &tw_timer_test_main;
1455
1456 clib_mem_init (0, 3ULL << 30);
1457
1458 unformat_init_command_line (&i, argv);
1459 error = timer_test_command_fn (tm, &i);
1460 unformat_free (&i);
1461
1462 if (error)
1463 {
1464 clib_error_report (error);
1465 return 1;
1466 }
1467 return 0;
1468}
1469#endif /* CLIB_UNIX */
1470
Dave Barach4af9ba12017-06-07 15:18:23 -04001471/* For debugging... */
1472int
1473pifi (void *p, u32 index)
1474{
1475 return pool_is_free_index (p, index);
1476}
1477
1478u32
1479vl (void *p)
1480{
1481 return vec_len (p);
1482}
1483
1484uword
1485pe (void *v)
1486{
1487 return (pool_elts (v));
1488}
1489
Dave Barach8e8f98c2017-02-03 11:58:53 -05001490/*
1491 * fd.io coding-style-patch-verification: ON
1492 *
1493 * Local Variables:
1494 * eval: (c-set-style "gnu")
1495 * End:
1496 */