1 1.1 christos /* This testcase is part of GDB, the GNU debugger. 2 1.1 christos 3 1.11 christos Copyright 2010-2024 Free Software Foundation, Inc. 4 1.1 christos 5 1.1 christos This program is free software; you can redistribute it and/or modify 6 1.1 christos it under the terms of the GNU General Public License as published by 7 1.1 christos the Free Software Foundation; either version 3 of the License, or 8 1.1 christos (at your option) any later version. 9 1.1 christos 10 1.1 christos This program is distributed in the hope that it will be useful, 11 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 12 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 1.1 christos GNU General Public License for more details. 14 1.1 christos 15 1.1 christos You should have received a copy of the GNU General Public License 16 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 1.1 christos 18 1.1 christos /* This program tests tracepoint speed. It consists of two identical 19 1.1 christos loops, which in normal execution will run for exactly the same 20 1.1 christos amount of time. A tracepoint in the second loop will slow it down 21 1.1 christos by some amount, and then the program will report the slowdown 22 1.1 christos observed. */ 23 1.1 christos 24 1.1 christos /* While primarily designed for the testsuite, it can also be used 25 1.1 christos for interactive testing. */ 26 1.1 christos 27 1.1 christos #include <stdio.h> 28 1.1 christos #include <time.h> 29 1.1 christos #include <sys/time.h> 30 1.1 christos #include <sys/resource.h> 31 1.8 christos #include <unistd.h> 32 1.1 christos 33 1.1 christos int trace_speed_test (void); 34 1.1 christos 35 1.1 christos /* We mark these globals as volatile so the speed-measuring loops 36 1.1 christos don't get totally emptied out at high optimization levels. */ 37 1.1 christos 38 1.1 christos volatile int globfoo, globfoo2, globfoo3; 39 1.1 christos 40 1.1 christos volatile short globarr[80000]; 41 1.1 christos 42 1.1 christos int init_iters = 10 * 1000; 43 1.1 christos 44 1.1 christos int iters; 45 1.1 christos 46 1.1 christos int max_iters = 1000 * 1000 * 1000; 47 1.1 christos 48 1.1 christos int numtps = 1; 49 1.1 christos 50 1.1 christos unsigned long long now2, now3, now4, now5; 51 1.1 christos int total1, total2, idelta, mindelta, nsdelta; 52 1.1 christos int nspertp = 0; 53 1.1 christos 54 1.1 christos /* Return CPU usage (both user and system - trap-based tracepoints use 55 1.1 christos a bunch of system time). */ 56 1.1 christos 57 1.1 christos unsigned long long 58 1.1 christos myclock () 59 1.1 christos { 60 1.6 christos struct timeval tm; 61 1.6 christos gettimeofday (&tm, NULL); 62 1.6 christos return (((unsigned long long) tm.tv_sec) * 1000000) + tm.tv_usec; 63 1.1 christos } 64 1.1 christos 65 1.1 christos int 66 1.1 christos main(int argc, char **argv) 67 1.1 christos { 68 1.1 christos int problem; 69 1.1 christos 70 1.1 christos iters = init_iters; 71 1.1 christos 72 1.1 christos while (1) 73 1.1 christos { 74 1.1 christos numtps = 1; /* set pre-run breakpoint here */ 75 1.1 christos 76 1.1 christos /* Keep trying the speed test, with more iterations, until 77 1.1 christos we get to a reasonable number. */ 78 1.9 christos while ((problem = trace_speed_test())) 79 1.1 christos { 80 1.1 christos /* If iteration isn't working, give up. */ 81 1.1 christos if (iters > max_iters) 82 1.1 christos { 83 1.1 christos printf ("Gone over %d iterations, giving up\n", max_iters); 84 1.1 christos break; 85 1.1 christos } 86 1.1 christos if (problem < 0) 87 1.1 christos { 88 1.8 christos printf ("Negative times, giving up\n"); 89 1.1 christos break; 90 1.1 christos } 91 1.1 christos 92 1.1 christos iters *= 2; 93 1.1 christos printf ("Doubled iterations to %d\n", iters); 94 1.1 christos } 95 1.1 christos 96 1.1 christos printf ("Tracepoint time is %d ns\n", nspertp); 97 1.1 christos 98 1.1 christos /* This is for the benefit of interactive testing and attaching, 99 1.1 christos keeps the program from pegging the machine. */ 100 1.1 christos sleep (1); /* set post-run breakpoint here */ 101 1.1 christos 102 1.1 christos /* Issue a little bit of output periodically, so we can see if 103 1.1 christos program is alive or hung. */ 104 1.1 christos printf ("%s keeping busy, clock=%llu\n", argv[0], myclock ()); 105 1.1 christos } 106 1.1 christos return 0; 107 1.1 christos } 108 1.1 christos 109 1.1 christos int 110 1.1 christos trace_speed_test (void) 111 1.1 christos { 112 1.1 christos int i; 113 1.1 christos 114 1.1 christos /* Overall loop run time deltas under 1 ms are likely noise and 115 1.1 christos should be ignored. */ 116 1.1 christos mindelta = 1000; 117 1.1 christos 118 1.1 christos // The bodies of the two loops following must be identical. 119 1.1 christos 120 1.1 christos now2 = myclock (); 121 1.1 christos globfoo2 = 1; 122 1.1 christos for (i = 0; i < iters; ++i) 123 1.1 christos { 124 1.1 christos globfoo2 *= 45; 125 1.1 christos globfoo2 += globfoo + globfoo3; 126 1.1 christos globfoo2 *= globfoo + globfoo3; 127 1.1 christos globfoo2 -= globarr[4] + globfoo3; 128 1.1 christos globfoo2 *= globfoo + globfoo3; 129 1.1 christos globfoo2 += globfoo + globfoo3; 130 1.1 christos } 131 1.1 christos now3 = myclock (); 132 1.1 christos total1 = now3 - now2; 133 1.1 christos 134 1.1 christos now4 = myclock (); 135 1.1 christos globfoo2 = 1; 136 1.1 christos for (i = 0; i < iters; ++i) 137 1.1 christos { 138 1.1 christos globfoo2 *= 45; 139 1.1 christos globfoo2 += globfoo + globfoo3; /* set tracepoint here */ 140 1.1 christos globfoo2 *= globfoo + globfoo3; 141 1.1 christos globfoo2 -= globarr[4] + globfoo3; 142 1.1 christos globfoo2 *= globfoo + globfoo3; 143 1.1 christos globfoo2 += globfoo + globfoo3; 144 1.1 christos } 145 1.1 christos now5 = myclock (); 146 1.1 christos total2 = now5 - now4; 147 1.1 christos 148 1.1 christos /* Report on the test results. */ 149 1.1 christos 150 1.1 christos nspertp = 0; 151 1.1 christos 152 1.1 christos idelta = total2 - total1; 153 1.1 christos 154 1.1 christos printf ("Loops took %d usec and %d usec, delta is %d usec, %d iterations\n", 155 1.1 christos total1, total2, idelta, iters); 156 1.1 christos 157 1.1 christos /* If the second loop seems to run faster, things are weird so give up. */ 158 1.1 christos if (idelta < 0) 159 1.1 christos return -1; 160 1.1 christos 161 1.1 christos if (idelta > mindelta 162 1.6 christos /* Total test time should be between 15 and 30 seconds. */ 163 1.6 christos && (total1 + total2) > (15 * 1000000) 164 1.6 christos && (total1 + total2) < (30 * 1000000)) 165 1.1 christos { 166 1.1 christos nsdelta = (((unsigned long long) idelta) * 1000) / iters; 167 1.1 christos printf ("Second loop took %d ns longer per iter than first\n", nsdelta); 168 1.1 christos nspertp = nsdelta / numtps; 169 1.1 christos printf ("%d ns per tracepoint\n", nspertp); 170 1.1 christos printf ("Base iteration time %d ns\n", 171 1.1 christos ((int) (((unsigned long long) total1) * 1000) / iters)); 172 1.1 christos printf ("Total test time %d secs\n", ((int) ((now5 - now2) / 1000000))); 173 1.1 christos 174 1.1 christos /* Speed test ran with no problem. */ 175 1.1 christos return 0; 176 1.1 christos } 177 1.1 christos 178 1.1 christos /* The test run was too brief, or otherwise not useful. */ 179 1.1 christos return 1; 180 1.1 christos } 181