xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/testsuite/gdb.trace/tspeed.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* This testcase is part of GDB, the GNU debugger.
2 
3    Copyright 2010-2023 Free Software Foundation, Inc.
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 #include <unistd.h>
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 {
60   struct timeval tm;
61   gettimeofday (&tm, NULL);
62   return (((unsigned long long) tm.tv_sec) * 1000000) + tm.tv_usec;
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.  */
78       while ((problem = trace_speed_test()))
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 	    {
88 	      printf ("Negative times, giving up\n");
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
162       /* Total test time should be between 15 and 30 seconds.  */
163       && (total1 + total2) > (15 * 1000000)
164       && (total1 + total2) < (30 * 1000000))
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 }
181