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