1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include "test.h" 6 7 #include <stdio.h> 8 #include <unistd.h> 9 #include <inttypes.h> 10 #include <rte_cycles.h> 11 #include <rte_timer.h> 12 #include <rte_common.h> 13 #include <rte_lcore.h> 14 #include <rte_random.h> 15 #include <rte_malloc.h> 16 #include <rte_pause.h> 17 18 #define MAX_ITERATIONS 1000000 19 20 int outstanding_count = 0; 21 22 static void 23 timer_cb(struct rte_timer *t __rte_unused, void *param __rte_unused) 24 { 25 outstanding_count--; 26 } 27 28 #define DELAY_SECONDS 1 29 30 #ifdef RTE_EXEC_ENV_LINUX 31 #define do_delay() usleep(10) 32 #else 33 #define do_delay() rte_pause() 34 #endif 35 36 static int 37 test_timer_perf(void) 38 { 39 unsigned iterations = 100; 40 unsigned i; 41 struct rte_timer *tms; 42 uint64_t start_tsc, end_tsc, delay_start; 43 unsigned lcore_id = rte_lcore_id(); 44 45 tms = rte_malloc(NULL, sizeof(*tms) * MAX_ITERATIONS, 0); 46 47 for (i = 0; i < MAX_ITERATIONS; i++) 48 rte_timer_init(&tms[i]); 49 50 const uint64_t ticks = rte_get_timer_hz() * DELAY_SECONDS; 51 const uint64_t ticks_per_ms = rte_get_tsc_hz()/1000; 52 const uint64_t ticks_per_us = ticks_per_ms/1000; 53 54 while (iterations <= MAX_ITERATIONS) { 55 56 printf("Appending %u timers\n", iterations); 57 start_tsc = rte_rdtsc(); 58 for (i = 0; i < iterations; i++) 59 rte_timer_reset(&tms[i], ticks, SINGLE, lcore_id, 60 timer_cb, NULL); 61 end_tsc = rte_rdtsc(); 62 printf("Time for %u timers: %"PRIu64" (%"PRIu64"ms), ", iterations, 63 end_tsc-start_tsc, (end_tsc-start_tsc+ticks_per_ms/2)/(ticks_per_ms)); 64 printf("Time per timer: %"PRIu64" (%"PRIu64"us)\n", 65 (end_tsc-start_tsc)/iterations, 66 ((end_tsc-start_tsc)/iterations+ticks_per_us/2)/(ticks_per_us)); 67 outstanding_count = iterations; 68 delay_start = rte_get_timer_cycles(); 69 while (rte_get_timer_cycles() < delay_start + ticks) 70 do_delay(); 71 72 start_tsc = rte_rdtsc(); 73 while (outstanding_count) 74 rte_timer_manage(); 75 end_tsc = rte_rdtsc(); 76 printf("Time for %u callbacks: %"PRIu64" (%"PRIu64"ms), ", iterations, 77 end_tsc-start_tsc, (end_tsc-start_tsc+ticks_per_ms/2)/(ticks_per_ms)); 78 printf("Time per callback: %"PRIu64" (%"PRIu64"us)\n", 79 (end_tsc-start_tsc)/iterations, 80 ((end_tsc-start_tsc)/iterations+ticks_per_us/2)/(ticks_per_us)); 81 82 printf("Resetting %u timers\n", iterations); 83 start_tsc = rte_rdtsc(); 84 for (i = 0; i < iterations; i++) 85 rte_timer_reset(&tms[i], rte_rand() % ticks, SINGLE, lcore_id, 86 timer_cb, NULL); 87 end_tsc = rte_rdtsc(); 88 printf("Time for %u timers: %"PRIu64" (%"PRIu64"ms), ", iterations, 89 end_tsc-start_tsc, (end_tsc-start_tsc+ticks_per_ms/2)/(ticks_per_ms)); 90 printf("Time per timer: %"PRIu64" (%"PRIu64"us)\n", 91 (end_tsc-start_tsc)/iterations, 92 ((end_tsc-start_tsc)/iterations+ticks_per_us/2)/(ticks_per_us)); 93 outstanding_count = iterations; 94 95 delay_start = rte_get_timer_cycles(); 96 while (rte_get_timer_cycles() < delay_start + ticks) 97 do_delay(); 98 99 rte_timer_manage(); 100 if (outstanding_count != 0) { 101 printf("Error: outstanding callback count = %d\n", outstanding_count); 102 return -1; 103 } 104 105 iterations *= 10; 106 printf("\n"); 107 } 108 109 printf("All timers processed ok\n"); 110 111 /* measure time to poll an empty timer list */ 112 start_tsc = rte_rdtsc(); 113 for (i = 0; i < iterations; i++) 114 rte_timer_manage(); 115 end_tsc = rte_rdtsc(); 116 printf("\nTime per rte_timer_manage with zero timers: %"PRIu64" cycles\n", 117 (end_tsc - start_tsc + iterations/2) / iterations); 118 119 /* measure time to poll a timer list with timers, but without 120 * calling any callbacks */ 121 rte_timer_reset(&tms[0], ticks * 100, SINGLE, lcore_id, 122 timer_cb, NULL); 123 start_tsc = rte_rdtsc(); 124 for (i = 0; i < iterations; i++) 125 rte_timer_manage(); 126 end_tsc = rte_rdtsc(); 127 printf("Time per rte_timer_manage with zero callbacks: %"PRIu64" cycles\n", 128 (end_tsc - start_tsc + iterations/2) / iterations); 129 130 rte_free(tms); 131 return 0; 132 } 133 134 REGISTER_PERF_TEST(timer_perf_autotest, test_timer_perf); 135