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