Commit | Line | Data |
---|---|---|
3c9057f3 SS |
1 | /* This testcase is part of GDB, the GNU debugger. |
2 | ||
618f726f | 3 | Copyright 2010-2016 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> | |
31 | ||
32 | int trace_speed_test (void); | |
33 | ||
34 | /* We mark these globals as volatile so the speed-measuring loops | |
35 | don't get totally emptied out at high optimization levels. */ | |
36 | ||
37 | volatile int globfoo, globfoo2, globfoo3; | |
38 | ||
39 | volatile short globarr[80000]; | |
40 | ||
41 | int init_iters = 10 * 1000; | |
42 | ||
43 | int iters; | |
44 | ||
45 | int max_iters = 1000 * 1000 * 1000; | |
46 | ||
47 | int numtps = 1; | |
48 | ||
49 | unsigned long long now2, now3, now4, now5; | |
50 | int total1, total2, idelta, mindelta, nsdelta; | |
51 | int nspertp = 0; | |
52 | ||
53 | /* Return CPU usage (both user and system - trap-based tracepoints use | |
54 | a bunch of system time). */ | |
55 | ||
56 | unsigned long long | |
57 | myclock () | |
58 | { | |
59 | struct timeval tm, tm2; | |
60 | struct rusage ru; | |
61 | getrusage (RUSAGE_SELF, &ru); | |
62 | tm = ru.ru_utime; | |
63 | tm2 = ru.ru_stime; | |
64 | return (((unsigned long long) tm.tv_sec) * 1000000) + tm.tv_usec | |
65 | + (((unsigned long long) tm2.tv_sec) * 1000000) + tm2.tv_usec; | |
66 | } | |
67 | ||
68 | int | |
69 | main(int argc, char **argv) | |
70 | { | |
71 | int problem; | |
72 | ||
73 | iters = init_iters; | |
74 | ||
75 | while (1) | |
76 | { | |
77 | numtps = 1; /* set pre-run breakpoint here */ | |
78 | ||
79 | /* Keep trying the speed test, with more iterations, until | |
80 | we get to a reasonable number. */ | |
81 | while (problem = trace_speed_test()) | |
82 | { | |
83 | /* If iteration isn't working, give up. */ | |
84 | if (iters > max_iters) | |
85 | { | |
86 | printf ("Gone over %d iterations, giving up\n", max_iters); | |
87 | break; | |
88 | } | |
89 | if (problem < 0) | |
90 | { | |
91 | printf ("Negative times, giving up\n", max_iters); | |
92 | break; | |
93 | } | |
94 | ||
95 | iters *= 2; | |
96 | printf ("Doubled iterations to %d\n", iters); | |
97 | } | |
98 | ||
99 | printf ("Tracepoint time is %d ns\n", nspertp); | |
100 | ||
101 | /* This is for the benefit of interactive testing and attaching, | |
102 | keeps the program from pegging the machine. */ | |
103 | sleep (1); /* set post-run breakpoint here */ | |
104 | ||
105 | /* Issue a little bit of output periodically, so we can see if | |
106 | program is alive or hung. */ | |
107 | printf ("%s keeping busy, clock=%llu\n", argv[0], myclock ()); | |
108 | } | |
109 | return 0; | |
110 | } | |
111 | ||
112 | int | |
113 | trace_speed_test (void) | |
114 | { | |
115 | int i; | |
116 | ||
117 | /* Overall loop run time deltas under 1 ms are likely noise and | |
118 | should be ignored. */ | |
119 | mindelta = 1000; | |
120 | ||
121 | // The bodies of the two loops following must be identical. | |
122 | ||
123 | now2 = myclock (); | |
124 | globfoo2 = 1; | |
125 | for (i = 0; i < iters; ++i) | |
126 | { | |
127 | globfoo2 *= 45; | |
128 | globfoo2 += globfoo + globfoo3; | |
129 | globfoo2 *= globfoo + globfoo3; | |
130 | globfoo2 -= globarr[4] + globfoo3; | |
131 | globfoo2 *= globfoo + globfoo3; | |
132 | globfoo2 += globfoo + globfoo3; | |
133 | } | |
134 | now3 = myclock (); | |
135 | total1 = now3 - now2; | |
136 | ||
137 | now4 = myclock (); | |
138 | globfoo2 = 1; | |
139 | for (i = 0; i < iters; ++i) | |
140 | { | |
141 | globfoo2 *= 45; | |
142 | globfoo2 += globfoo + globfoo3; /* set tracepoint here */ | |
143 | globfoo2 *= globfoo + globfoo3; | |
144 | globfoo2 -= globarr[4] + globfoo3; | |
145 | globfoo2 *= globfoo + globfoo3; | |
146 | globfoo2 += globfoo + globfoo3; | |
147 | } | |
148 | now5 = myclock (); | |
149 | total2 = now5 - now4; | |
150 | ||
151 | /* Report on the test results. */ | |
152 | ||
153 | nspertp = 0; | |
154 | ||
155 | idelta = total2 - total1; | |
156 | ||
157 | printf ("Loops took %d usec and %d usec, delta is %d usec, %d iterations\n", | |
158 | total1, total2, idelta, iters); | |
159 | ||
160 | /* If the second loop seems to run faster, things are weird so give up. */ | |
161 | if (idelta < 0) | |
162 | return -1; | |
163 | ||
164 | if (idelta > mindelta | |
165 | /* Total test time should be between 2 and 5 seconds. */ | |
166 | && (total1 + total2) > (2 * 1000000) | |
167 | && (total1 + total2) < (5 * 1000000)) | |
168 | { | |
169 | nsdelta = (((unsigned long long) idelta) * 1000) / iters; | |
170 | printf ("Second loop took %d ns longer per iter than first\n", nsdelta); | |
171 | nspertp = nsdelta / numtps; | |
172 | printf ("%d ns per tracepoint\n", nspertp); | |
173 | printf ("Base iteration time %d ns\n", | |
174 | ((int) (((unsigned long long) total1) * 1000) / iters)); | |
175 | printf ("Total test time %d secs\n", ((int) ((now5 - now2) / 1000000))); | |
176 | ||
177 | /* Speed test ran with no problem. */ | |
178 | return 0; | |
179 | } | |
180 | ||
181 | /* The test run was too brief, or otherwise not useful. */ | |
182 | return 1; | |
183 | } |