ode/src/timer.cpp
changeset 0 2f259fa3e83a
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 /*************************************************************************
       
     2  *                                                                       *
       
     3  * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
       
     4  * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
       
     5  *                                                                       *
       
     6  * This library is free software; you can redistribute it and/or         *
       
     7  * modify it under the terms of EITHER:                                  *
       
     8  *   (1) The GNU Lesser General Public License as published by the Free  *
       
     9  *       Software Foundation; either version 2.1 of the License, or (at  *
       
    10  *       your option) any later version. The text of the GNU Lesser      *
       
    11  *       General Public License is included with this library in the     *
       
    12  *       file LICENSE.TXT.                                               *
       
    13  *   (2) The BSD-style license that is included with this library in     *
       
    14  *       the file LICENSE-BSD.TXT.                                       *
       
    15  *                                                                       *
       
    16  * This library is distributed in the hope that it will be useful,       *
       
    17  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
       
    18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
       
    19  * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
       
    20  *                                                                       *
       
    21  *************************************************************************/
       
    22 
       
    23 /*
       
    24 
       
    25 TODO
       
    26 ----
       
    27 
       
    28 * gettimeofday() and the pentium time stamp counter return the real time,
       
    29   not the process time. fix this somehow!
       
    30 
       
    31 */
       
    32 
       
    33 #include <ode/common.h>
       
    34 #include <ode/timer.h>
       
    35 #include <ode/ode.h>
       
    36 
       
    37 // misc defines
       
    38 #define ALLOCA dALLOCA16
       
    39 
       
    40 
       
    41 #include <sys/time.h>
       
    42 #include <unistd.h>
       
    43 
       
    44 
       
    45 static inline void getClockCount (unsigned long cc[2])
       
    46 {
       
    47   struct timeval tv;
       
    48   gettimeofday (&tv,0);
       
    49   cc[0] = tv.tv_usec;
       
    50   cc[1] = tv.tv_sec;
       
    51 }
       
    52 
       
    53 
       
    54 static inline void serialize()
       
    55 {
       
    56 }
       
    57 
       
    58 
       
    59 static inline double loadClockCount (unsigned long a[2])
       
    60 {
       
    61   return a[1]*1.0e6 + a[0];
       
    62 }
       
    63 
       
    64 
       
    65 EXPORT_C double dTimerResolution()
       
    66 {
       
    67   unsigned long cc1[2],cc2[2];
       
    68   getClockCount (cc1);
       
    69   do {
       
    70     getClockCount (cc2);
       
    71   }
       
    72   while (cc1[0]==cc2[0] && cc1[1]==cc2[1]);
       
    73   do {
       
    74     getClockCount (cc1);
       
    75   }
       
    76   while (cc1[0]==cc2[0] && cc1[1]==cc2[1]);
       
    77   double t1 = loadClockCount (cc1);
       
    78   double t2 = loadClockCount (cc2);
       
    79   return (t1-t2) / dTimerTicksPerSecond();
       
    80 }
       
    81 
       
    82 
       
    83 EXPORT_C double dTimerTicksPerSecond()
       
    84 {
       
    85   return 1000000;
       
    86 }
       
    87 
       
    88 //****************************************************************************
       
    89 // stop watches
       
    90 
       
    91 EXPORT_C void dStopwatchReset (dStopwatch *s)
       
    92 {
       
    93   s->time = 0;
       
    94   s->cc[0] = 0;
       
    95   s->cc[1] = 0;
       
    96 }
       
    97 
       
    98 
       
    99 EXPORT_C void dStopwatchStart (dStopwatch *s)
       
   100 {
       
   101   serialize();
       
   102   getClockCount (s->cc);
       
   103 }
       
   104 
       
   105 
       
   106 EXPORT_C void dStopwatchStop  (dStopwatch *s)
       
   107 {
       
   108   unsigned long cc[2];
       
   109   serialize();
       
   110   getClockCount (cc);
       
   111   double t1 = loadClockCount (s->cc);
       
   112   double t2 = loadClockCount (cc);
       
   113   s->time += t2-t1;
       
   114 }
       
   115 
       
   116 
       
   117 EXPORT_C double dStopwatchTime (dStopwatch *s)
       
   118 {
       
   119   return s->time / dTimerTicksPerSecond();
       
   120 }
       
   121 
       
   122 //****************************************************************************
       
   123 // code timers
       
   124 
       
   125 // maximum number of events to record
       
   126 
       
   127 
       
   128 // make sure all slot totals and counts reset to 0 at start
       
   129 
       
   130 static void initSlots()
       
   131 {
       
   132   static int initialized=0;
       
   133   if (!initialized) {
       
   134     for (int i=0; i<MAXNUM; i++) {
       
   135       GetGlobalData()->event[i].count = 0;
       
   136       GetGlobalData()->event[i].total_t = 0;
       
   137       GetGlobalData()->event[i].total_p = 0;
       
   138     }
       
   139     initialized = 1;
       
   140   }
       
   141 }
       
   142 
       
   143 
       
   144 EXPORT_C void dTimerStart (const char *description)
       
   145 {
       
   146   initSlots();
       
   147   GetGlobalData()->event[0].description = const_cast<char*> (description);
       
   148   GetGlobalData()->num = 1;
       
   149   serialize();
       
   150   getClockCount (GetGlobalData()->event[0].cc);
       
   151 }
       
   152 
       
   153 
       
   154 EXPORT_C void dTimerNow (const char *description)
       
   155 {
       
   156   if (GetGlobalData()->num < MAXNUM) {
       
   157     // do not serialize
       
   158     getClockCount (GetGlobalData()->event[GetGlobalData()->num].cc);
       
   159     GetGlobalData()->event[GetGlobalData()->num].description = const_cast<char*> (description);
       
   160     GetGlobalData()->num++;
       
   161   }
       
   162 }
       
   163 
       
   164 
       
   165 EXPORT_C void dTimerEnd()
       
   166 {
       
   167   if (GetGlobalData()->num < MAXNUM) {
       
   168     serialize();
       
   169     getClockCount (GetGlobalData()->event[GetGlobalData()->num].cc);
       
   170     GetGlobalData()->event[GetGlobalData()->num].description = "TOTAL";
       
   171     GetGlobalData()->num++;
       
   172   }
       
   173 }
       
   174 
       
   175 //****************************************************************************
       
   176 // print report
       
   177 
       
   178 static void fprintDoubleWithPrefix (FILE *f, double a, char *fmt)
       
   179 {
       
   180   if (a >= 0.999999) {
       
   181     fprintf (f,fmt,a);
       
   182     return;
       
   183   }
       
   184   a *= 1000.0;
       
   185   if (a >= 0.999999) {
       
   186     fprintf (f,fmt,a);
       
   187     fprintf (f,"m");
       
   188     return;
       
   189   }
       
   190   a *= 1000.0;
       
   191   if (a >= 0.999999) {
       
   192     fprintf (f,fmt,a);
       
   193     fprintf (f,"u");
       
   194     return;
       
   195   }
       
   196   a *= 1000.0;
       
   197   fprintf (f,fmt,a);
       
   198   fprintf (f,"n");
       
   199 }
       
   200 
       
   201 
       
   202 EXPORT_C void dTimerReport (FILE *fout, int average)
       
   203 {
       
   204   int i;
       
   205   size_t maxl;
       
   206   double ccunit = 1.0/dTimerTicksPerSecond();
       
   207   fprintf (fout,"\nTimer Report (");
       
   208   fprintDoubleWithPrefix (fout,ccunit,"%.2f ");
       
   209   fprintf (fout,"s resolution)\n------------\n");
       
   210   if (GetGlobalData()->num < 1) return;
       
   211 
       
   212   // get maximum description length
       
   213   maxl = 0;
       
   214   for (i=0; i<GetGlobalData()->num; i++) {
       
   215     size_t l = strlen (GetGlobalData()->event[i].description);
       
   216     if (l > maxl) maxl = l;
       
   217   }
       
   218 
       
   219   // calculate total time
       
   220   double t1 = loadClockCount (GetGlobalData()->event[0].cc);
       
   221   double t2 = loadClockCount (GetGlobalData()->event[GetGlobalData()->num-1].cc);
       
   222   double total = t2 - t1;
       
   223   if (total <= 0) total = 1;
       
   224 
       
   225   // compute time difference for all slots except the last one. update totals
       
   226   double *times = (double*) malloc (GetGlobalData()->num * sizeof(double));
       
   227   if (times == NULL) {
       
   228   	return;
       
   229   }
       
   230   for (i=0; i < (GetGlobalData()->num-1); i++) {
       
   231     double t1 = loadClockCount (GetGlobalData()->event[i].cc);
       
   232     double t2 = loadClockCount (GetGlobalData()->event[i+1].cc);
       
   233     times[i] = t2 - t1;
       
   234     GetGlobalData()->event[i].count++;
       
   235     GetGlobalData()->event[i].total_t += times[i];
       
   236     GetGlobalData()->event[i].total_p += times[i]/total * 100.0;
       
   237   }
       
   238 
       
   239   // print report (with optional averages)
       
   240   for (i=0; i<GetGlobalData()->num; i++) {
       
   241     double t,p;
       
   242     if (i < (GetGlobalData()->num-1)) {
       
   243       t = times[i];
       
   244       p = t/total * 100.0;
       
   245     }
       
   246     else {
       
   247       t = total;
       
   248       p = 100.0;
       
   249     }
       
   250     fprintf (fout,"%-*s %7.2fms %6.2f%%",maxl,GetGlobalData()->event[i].description,
       
   251 	     t*ccunit * 1000.0, p);
       
   252     if (average && i < (GetGlobalData()->num-1)) {
       
   253       fprintf (fout,"  (avg %7.2fms %6.2f%%)",
       
   254 	       (GetGlobalData()->event[i].total_t / GetGlobalData()->event[i].count)*ccunit * 1000.0,
       
   255 	       GetGlobalData()->event[i].total_p / GetGlobalData()->event[i].count);
       
   256     }
       
   257     fprintf (fout,"\n");
       
   258   }
       
   259   fprintf (fout,"\n");
       
   260   
       
   261   free(times);
       
   262 }