aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.trace/tspeed.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/testsuite/gdb.trace/tspeed.c')
-rw-r--r--gdb/testsuite/gdb.trace/tspeed.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.trace/tspeed.c b/gdb/testsuite/gdb.trace/tspeed.c
new file mode 100644
index 0000000..cf698f9
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/tspeed.c
@@ -0,0 +1,184 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2010, 2011
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* This program tests tracepoint speed. It consists of two identical
+ loops, which in normal execution will run for exactly the same
+ amount of time. A tracepoint in the second loop will slow it down
+ by some amount, and then the program will report the slowdown
+ observed. */
+
+/* While primarily designed for the testsuite, it can also be used
+ for interactive testing. */
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+int trace_speed_test (void);
+
+/* We mark these globals as volatile so the speed-measuring loops
+ don't get totally emptied out at high optimization levels. */
+
+volatile int globfoo, globfoo2, globfoo3;
+
+volatile short globarr[80000];
+
+int init_iters = 10 * 1000;
+
+int iters;
+
+int max_iters = 1000 * 1000 * 1000;
+
+int numtps = 1;
+
+unsigned long long now2, now3, now4, now5;
+int total1, total2, idelta, mindelta, nsdelta;
+int nspertp = 0;
+
+/* Return CPU usage (both user and system - trap-based tracepoints use
+ a bunch of system time). */
+
+unsigned long long
+myclock ()
+{
+ struct timeval tm, tm2;
+ struct rusage ru;
+ getrusage (RUSAGE_SELF, &ru);
+ tm = ru.ru_utime;
+ tm2 = ru.ru_stime;
+ return (((unsigned long long) tm.tv_sec) * 1000000) + tm.tv_usec
+ + (((unsigned long long) tm2.tv_sec) * 1000000) + tm2.tv_usec;
+}
+
+int
+main(int argc, char **argv)
+{
+ int problem;
+
+ iters = init_iters;
+
+ while (1)
+ {
+ numtps = 1; /* set pre-run breakpoint here */
+
+ /* Keep trying the speed test, with more iterations, until
+ we get to a reasonable number. */
+ while (problem = trace_speed_test())
+ {
+ /* If iteration isn't working, give up. */
+ if (iters > max_iters)
+ {
+ printf ("Gone over %d iterations, giving up\n", max_iters);
+ break;
+ }
+ if (problem < 0)
+ {
+ printf ("Negative times, giving up\n", max_iters);
+ break;
+ }
+
+ iters *= 2;
+ printf ("Doubled iterations to %d\n", iters);
+ }
+
+ printf ("Tracepoint time is %d ns\n", nspertp);
+
+ /* This is for the benefit of interactive testing and attaching,
+ keeps the program from pegging the machine. */
+ sleep (1); /* set post-run breakpoint here */
+
+ /* Issue a little bit of output periodically, so we can see if
+ program is alive or hung. */
+ printf ("%s keeping busy, clock=%llu\n", argv[0], myclock ());
+ }
+ return 0;
+}
+
+int
+trace_speed_test (void)
+{
+ int i;
+
+ /* Overall loop run time deltas under 1 ms are likely noise and
+ should be ignored. */
+ mindelta = 1000;
+
+ // The bodies of the two loops following must be identical.
+
+ now2 = myclock ();
+ globfoo2 = 1;
+ for (i = 0; i < iters; ++i)
+ {
+ globfoo2 *= 45;
+ globfoo2 += globfoo + globfoo3;
+ globfoo2 *= globfoo + globfoo3;
+ globfoo2 -= globarr[4] + globfoo3;
+ globfoo2 *= globfoo + globfoo3;
+ globfoo2 += globfoo + globfoo3;
+ }
+ now3 = myclock ();
+ total1 = now3 - now2;
+
+ now4 = myclock ();
+ globfoo2 = 1;
+ for (i = 0; i < iters; ++i)
+ {
+ globfoo2 *= 45;
+ globfoo2 += globfoo + globfoo3; /* set tracepoint here */
+ globfoo2 *= globfoo + globfoo3;
+ globfoo2 -= globarr[4] + globfoo3;
+ globfoo2 *= globfoo + globfoo3;
+ globfoo2 += globfoo + globfoo3;
+ }
+ now5 = myclock ();
+ total2 = now5 - now4;
+
+ /* Report on the test results. */
+
+ nspertp = 0;
+
+ idelta = total2 - total1;
+
+ printf ("Loops took %d usec and %d usec, delta is %d usec, %d iterations\n",
+ total1, total2, idelta, iters);
+
+ /* If the second loop seems to run faster, things are weird so give up. */
+ if (idelta < 0)
+ return -1;
+
+ if (idelta > mindelta
+ /* Total test time should be between 2 and 5 seconds. */
+ && (total1 + total2) > (2 * 1000000)
+ && (total1 + total2) < (5 * 1000000))
+ {
+ nsdelta = (((unsigned long long) idelta) * 1000) / iters;
+ printf ("Second loop took %d ns longer per iter than first\n", nsdelta);
+ nspertp = nsdelta / numtps;
+ printf ("%d ns per tracepoint\n", nspertp);
+ printf ("Base iteration time %d ns\n",
+ ((int) (((unsigned long long) total1) * 1000) / iters));
+ printf ("Total test time %d secs\n", ((int) ((now5 - now2) / 1000000)));
+
+ /* Speed test ran with no problem. */
+ return 0;
+ }
+
+ /* The test run was too brief, or otherwise not useful. */
+ return 1;
+}