1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "test.h" 35 36 #ifdef RTE_LIBRTE_TIMER 37 #include <stdio.h> 38 #include <unistd.h> 39 #include <inttypes.h> 40 #include <rte_cycles.h> 41 #include <rte_timer.h> 42 #include <rte_common.h> 43 #include <rte_lcore.h> 44 #include <rte_random.h> 45 #include <rte_malloc.h> 46 47 #define MAX_ITERATIONS 1000000 48 49 int outstanding_count = 0; 50 51 static void 52 timer_cb(struct rte_timer *t __rte_unused, void *param __rte_unused) 53 { 54 outstanding_count--; 55 } 56 57 #define DELAY_SECONDS 1 58 59 #ifdef RTE_EXEC_ENV_LINUXAPP 60 #define do_delay() usleep(10) 61 #else 62 #define do_delay() rte_pause() 63 #endif 64 65 int 66 test_timer_perf(void) 67 { 68 unsigned iterations = 100; 69 unsigned i; 70 struct rte_timer *tms; 71 uint64_t start_tsc, end_tsc, delay_start; 72 unsigned lcore_id = rte_lcore_id(); 73 74 tms = rte_malloc(NULL, sizeof(*tms) * MAX_ITERATIONS, 0); 75 76 for (i = 0; i < MAX_ITERATIONS; i++) 77 rte_timer_init(&tms[i]); 78 79 const uint64_t ticks = rte_get_timer_hz() * DELAY_SECONDS; 80 const uint64_t ticks_per_ms = rte_get_tsc_hz()/1000; 81 const uint64_t ticks_per_us = ticks_per_ms/1000; 82 83 while (iterations <= MAX_ITERATIONS) { 84 85 printf("Appending %u timers\n", iterations); 86 start_tsc = rte_rdtsc(); 87 for (i = 0; i < iterations; i++) 88 rte_timer_reset(&tms[i], ticks, SINGLE, lcore_id, 89 timer_cb, NULL); 90 end_tsc = rte_rdtsc(); 91 printf("Time for %u timers: %"PRIu64" (%"PRIu64"ms), ", iterations, 92 end_tsc-start_tsc, (end_tsc-start_tsc+ticks_per_ms/2)/(ticks_per_ms)); 93 printf("Time per timer: %"PRIu64" (%"PRIu64"us)\n", 94 (end_tsc-start_tsc)/iterations, 95 ((end_tsc-start_tsc)/iterations+ticks_per_us/2)/(ticks_per_us)); 96 outstanding_count = iterations; 97 delay_start = rte_get_timer_cycles(); 98 while (rte_get_timer_cycles() < delay_start + ticks) 99 do_delay(); 100 101 start_tsc = rte_rdtsc(); 102 while (outstanding_count) 103 rte_timer_manage(); 104 end_tsc = rte_rdtsc(); 105 printf("Time for %u callbacks: %"PRIu64" (%"PRIu64"ms), ", iterations, 106 end_tsc-start_tsc, (end_tsc-start_tsc+ticks_per_ms/2)/(ticks_per_ms)); 107 printf("Time per callback: %"PRIu64" (%"PRIu64"us)\n", 108 (end_tsc-start_tsc)/iterations, 109 ((end_tsc-start_tsc)/iterations+ticks_per_us/2)/(ticks_per_us)); 110 111 printf("Resetting %u timers\n", iterations); 112 start_tsc = rte_rdtsc(); 113 for (i = 0; i < iterations; i++) 114 rte_timer_reset(&tms[i], rte_rand() % ticks, SINGLE, lcore_id, 115 timer_cb, NULL); 116 end_tsc = rte_rdtsc(); 117 printf("Time for %u timers: %"PRIu64" (%"PRIu64"ms), ", iterations, 118 end_tsc-start_tsc, (end_tsc-start_tsc+ticks_per_ms/2)/(ticks_per_ms)); 119 printf("Time per timer: %"PRIu64" (%"PRIu64"us)\n", 120 (end_tsc-start_tsc)/iterations, 121 ((end_tsc-start_tsc)/iterations+ticks_per_us/2)/(ticks_per_us)); 122 outstanding_count = iterations; 123 124 delay_start = rte_get_timer_cycles(); 125 while (rte_get_timer_cycles() < delay_start + ticks) 126 do_delay(); 127 128 rte_timer_manage(); 129 if (outstanding_count != 0) { 130 printf("Error: outstanding callback count = %d\n", outstanding_count); 131 return -1; 132 } 133 134 iterations *= 10; 135 printf("\n"); 136 } 137 138 printf("All timers processed ok\n"); 139 140 /* measure time to poll an empty timer list */ 141 start_tsc = rte_rdtsc(); 142 for (i = 0; i < iterations; i++) 143 rte_timer_manage(); 144 end_tsc = rte_rdtsc(); 145 printf("\nTime per rte_timer_manage with zero timers: %"PRIu64" cycles\n", 146 (end_tsc - start_tsc + iterations/2) / iterations); 147 148 /* measure time to poll a timer list with timers, but without 149 * calling any callbacks */ 150 rte_timer_reset(&tms[0], ticks * 100, SINGLE, lcore_id, 151 timer_cb, NULL); 152 start_tsc = rte_rdtsc(); 153 for (i = 0; i < iterations; i++) 154 rte_timer_manage(); 155 end_tsc = rte_rdtsc(); 156 printf("Time per rte_timer_manage with zero callbacks: %"PRIu64" cycles\n", 157 (end_tsc - start_tsc + iterations/2) / iterations); 158 159 return 0; 160 } 161 162 #else 163 164 int 165 test_timer_perf(void) 166 { 167 return 0; 168 } 169 170 #endif 171