Home | History | Annotate | Line # | Download | only in gdb.trace
tspeed.c revision 1.1
      1 /* This testcase is part of GDB, the GNU debugger.
      2 
      3    Copyright 2010-2014 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 
     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 }
    184