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 <stdio.h> 35 #include <unistd.h> 36 #include <inttypes.h> 37 #include <rte_cycles.h> 38 #include <rte_timer.h> 39 #include <rte_common.h> 40 #include <rte_lcore.h> 41 #include <rte_random.h> 42 #include <rte_malloc.h> 43 #include "test.h" 44 45 #define MAX_ITERATIONS 1000000 46 47 int outstanding_count = 0; 48 49 static void 50 timer_cb(struct rte_timer *t __rte_unused, void *param __rte_unused) 51 { 52 outstanding_count--; 53 } 54 55 #define DELAY_SECONDS 1 56 57 #ifdef RTE_EXEC_ENV_LINUXAPP 58 #define do_delay() usleep(10) 59 #else 60 #define do_delay() rte_pause() 61 #endif 62 63 int 64 test_timer_perf(void) 65 { 66 unsigned iterations = 100; 67 unsigned i; 68 struct rte_timer *tms; 69 uint64_t start_tsc, end_tsc, delay_start; 70 unsigned lcore_id = rte_lcore_id(); 71 72 tms = rte_malloc(NULL, sizeof(*tms) * MAX_ITERATIONS, 0); 73 74 for (i = 0; i < MAX_ITERATIONS; i++) 75 rte_timer_init(&tms[i]); 76 77 const uint64_t ticks = rte_get_timer_hz() * DELAY_SECONDS; 78 const uint64_t ticks_per_ms = rte_get_tsc_hz()/1000; 79 const uint64_t ticks_per_us = ticks_per_ms/1000; 80 81 while (iterations <= MAX_ITERATIONS) { 82 83 printf("Appending %u timers\n", iterations); 84 start_tsc = rte_rdtsc(); 85 for (i = 0; i < iterations; i++) 86 rte_timer_reset(&tms[i], ticks, SINGLE, lcore_id, 87 timer_cb, NULL); 88 end_tsc = rte_rdtsc(); 89 printf("Time for %u timers: %"PRIu64" (%"PRIu64"ms), ", iterations, 90 end_tsc-start_tsc, (end_tsc-start_tsc+ticks_per_ms/2)/(ticks_per_ms)); 91 printf("Time per timer: %"PRIu64" (%"PRIu64"us)\n", 92 (end_tsc-start_tsc)/iterations, 93 ((end_tsc-start_tsc)/iterations+ticks_per_us/2)/(ticks_per_us)); 94 outstanding_count = iterations; 95 delay_start = rte_get_timer_cycles(); 96 while (rte_get_timer_cycles() < delay_start + ticks) 97 do_delay(); 98 99 start_tsc = rte_rdtsc(); 100 while (outstanding_count) 101 rte_timer_manage(); 102 end_tsc = rte_rdtsc(); 103 printf("Time for %u callbacks: %"PRIu64" (%"PRIu64"ms), ", iterations, 104 end_tsc-start_tsc, (end_tsc-start_tsc+ticks_per_ms/2)/(ticks_per_ms)); 105 printf("Time per callback: %"PRIu64" (%"PRIu64"us)\n", 106 (end_tsc-start_tsc)/iterations, 107 ((end_tsc-start_tsc)/iterations+ticks_per_us/2)/(ticks_per_us)); 108 109 printf("Resetting %u timers\n", iterations); 110 start_tsc = rte_rdtsc(); 111 for (i = 0; i < iterations; i++) 112 rte_timer_reset(&tms[i], rte_rand() % ticks, SINGLE, lcore_id, 113 timer_cb, NULL); 114 end_tsc = rte_rdtsc(); 115 printf("Time for %u timers: %"PRIu64" (%"PRIu64"ms), ", iterations, 116 end_tsc-start_tsc, (end_tsc-start_tsc+ticks_per_ms/2)/(ticks_per_ms)); 117 printf("Time per timer: %"PRIu64" (%"PRIu64"us)\n", 118 (end_tsc-start_tsc)/iterations, 119 ((end_tsc-start_tsc)/iterations+ticks_per_us/2)/(ticks_per_us)); 120 outstanding_count = iterations; 121 122 delay_start = rte_get_timer_cycles(); 123 while (rte_get_timer_cycles() < delay_start + ticks) 124 do_delay(); 125 126 rte_timer_manage(); 127 if (outstanding_count != 0) { 128 printf("Error: outstanding callback count = %d\n", outstanding_count); 129 return -1; 130 } 131 132 iterations *= 10; 133 printf("\n"); 134 } 135 136 printf("All timers processed ok\n"); 137 138 /* measure time to poll an empty timer list */ 139 start_tsc = rte_rdtsc(); 140 for (i = 0; i < iterations; i++) 141 rte_timer_manage(); 142 end_tsc = rte_rdtsc(); 143 printf("\nTime per rte_timer_manage with zero timers: %"PRIu64" cycles\n", 144 (end_tsc - start_tsc + iterations/2) / iterations); 145 146 /* measure time to poll a timer list with timers, but without 147 * calling any callbacks */ 148 rte_timer_reset(&tms[0], ticks * 100, SINGLE, lcore_id, 149 timer_cb, NULL); 150 start_tsc = rte_rdtsc(); 151 for (i = 0; i < iterations; i++) 152 rte_timer_manage(); 153 end_tsc = rte_rdtsc(); 154 printf("Time per rte_timer_manage with zero callbacks: %"PRIu64" cycles\n", 155 (end_tsc - start_tsc + iterations/2) / iterations); 156 157 return 0; 158 } 159