timer42.c

Go to the documentation of this file.
00001 /*                       T I M E R 4 2 . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1985-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** @addtogroup timer */
00023 /*@{*/
00024 /** @file timer42.c
00025  * To provide timing information for RT when running on 4.2 BSD UNIX.
00026  *
00027  *  Source -
00028  *      SECAD/VLD Computing Consortium, Bldg 394
00029  *      The U. S. Army Ballistic Research Laboratory
00030  *      Aberdeen Proving Ground, Maryland  21005
00031  *
00032  */
00033 
00034 #ifndef lint
00035 static const char RCStimer[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/timer42.c,v 14.11 2006/09/16 02:04:26 lbutler Exp $ (BRL)";
00036 #endif
00037 
00038 #include "common.h"
00039 
00040 
00041 
00042 #include <stdio.h>
00043 #include <string.h>
00044 #include <sys/types.h>
00045 #include <sys/time.h>
00046 #include <sys/resource.h>
00047 
00048 #include "machine.h"
00049 #include "bu.h"
00050 #include "vmath.h"
00051 #include "raytrace.h"
00052 
00053 static struct   timeval time0;  /* Time at which timeing started */
00054 static struct   rusage ru0;     /* Resource utilization at the start */
00055 static struct   rusage ru0c;    /* Resource utilization at the start */
00056 
00057 static void prusage(register struct rusage *r0, register struct rusage *r1, struct timeval *e, struct timeval *b, struct bu_vls *vp);
00058 #if 0
00059 static void tvadd();
00060 #endif
00061 static void tvsub(struct timeval *tdiff, struct timeval *t1, struct timeval *t0);
00062 static void psecs(long int l, struct bu_vls *vp);
00063 
00064 
00065 
00066 /*
00067  *                      R T _ P R E P _ T I M E R
00068  */
00069 void
00070 rt_prep_timer(void)
00071 {
00072         gettimeofday(&time0, (struct timezone *)0);
00073         getrusage(RUSAGE_SELF, &ru0);
00074         getrusage(RUSAGE_CHILDREN, &ru0c);
00075 }
00076 
00077 /*
00078  *                      R T _ G E T _ T I M E R
00079  *
00080  *  Reports on the passage of time, since rt_prep_timer() was called.
00081  *  Explicit return is number of CPU seconds.
00082  *  String return is descriptive.
00083  *  If "elapsed" pointer is non-null, number of elapsed seconds are returned.
00084  *  Times returned will never be zero.
00085  */
00086 double
00087 rt_get_timer(struct bu_vls *vp, double *elapsed)
00088 {
00089         struct timeval timedol;
00090         struct rusage ru1;
00091         struct rusage ru1c;
00092         struct timeval td;
00093         double  user_cpu_secs;
00094         double  elapsed_secs;
00095 
00096 
00097         getrusage(RUSAGE_SELF, &ru1);
00098         getrusage(RUSAGE_CHILDREN, &ru1c);
00099         gettimeofday(&timedol, (struct timezone *)0);
00100 
00101         elapsed_secs = (timedol.tv_sec - time0.tv_sec) +
00102                 (timedol.tv_usec - time0.tv_usec)/1000000.0;
00103 
00104         tvsub( &td, &ru1.ru_utime, &ru0.ru_utime );
00105         user_cpu_secs = td.tv_sec + ((double)td.tv_usec) / 1000000.0;
00106 
00107         tvsub( &td, &ru1c.ru_utime, &ru0c.ru_utime );
00108         user_cpu_secs += td.tv_sec + ((double)td.tv_usec) / 1000000.0;
00109 
00110         if( user_cpu_secs < 0.00001 )  user_cpu_secs = 0.00001;
00111         if( elapsed_secs < 0.00001 )  elapsed_secs = user_cpu_secs;     /* It can't be any less! */
00112 
00113         if( elapsed )  *elapsed = elapsed_secs;
00114 
00115         if( vp )  {
00116                 bu_vls_printf( vp, "cpu = %g sec, elapsed = %g sec\n",
00117                         user_cpu_secs, elapsed_secs );
00118                 bu_vls_strcat( vp, "    parent: " );
00119                 prusage(&ru0, &ru1, &timedol, &time0, vp);
00120                 bu_vls_strcat( vp, "\n  children: ");
00121                 prusage(&ru0c, &ru1c, &timedol, &time0, vp);
00122         }
00123 
00124         return( user_cpu_secs );
00125 }
00126 
00127 static void
00128 prusage(register struct rusage *r0, register struct rusage *r1, struct timeval *e, struct timeval *b, struct bu_vls *vp)
00129 {
00130         struct timeval tdiff;
00131         register time_t t;
00132         register char *cp;
00133         register int i;
00134         int ms;
00135 
00136         BU_CK_VLS(vp);
00137 
00138         t = (r1->ru_utime.tv_sec-r0->ru_utime.tv_sec)*100+
00139             (r1->ru_utime.tv_usec-r0->ru_utime.tv_usec)/10000+
00140             (r1->ru_stime.tv_sec-r0->ru_stime.tv_sec)*100+
00141             (r1->ru_stime.tv_usec-r0->ru_stime.tv_usec)/10000;
00142         ms =  (e->tv_sec-b->tv_sec)*100 + (e->tv_usec-b->tv_usec)/10000;
00143 
00144         cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw";
00145         for (; *cp; cp++)  {
00146                 if (*cp != '%')
00147                         bu_vls_putc( vp, *cp );
00148                 else if (cp[1]) switch(*++cp) {
00149 
00150                 case 'U':
00151                         tvsub(&tdiff, &r1->ru_utime, &r0->ru_utime);
00152                         bu_vls_printf(vp, "%ld.%01ld", (long)tdiff.tv_sec, (long)(tdiff.tv_usec/100000));
00153                         break;
00154 
00155                 case 'S':
00156                         tvsub(&tdiff, &r1->ru_stime, &r0->ru_stime);
00157                         bu_vls_printf(vp, "%ld.%01ld", (long)tdiff.tv_sec, (long)(tdiff.tv_usec/100000));
00158                         break;
00159 
00160                 case 'E':
00161                         psecs(ms / 100, vp);
00162                         break;
00163 
00164                 case 'P':
00165                         bu_vls_printf(vp, "%d%%", (int) (t*100 / ((ms ? ms : 1))));
00166                         break;
00167 
00168                 case 'W':
00169                         i = r1->ru_nswap - r0->ru_nswap;
00170                         bu_vls_printf(vp, "%d", i);
00171                         break;
00172 
00173                 case 'X':
00174                         bu_vls_printf(vp, "%ld", (long)(t == 0 ? 0 : (r1->ru_ixrss-r0->ru_ixrss)/t));
00175                         break;
00176 
00177                 case 'D':
00178                         bu_vls_printf(vp, "%ld", (long)(t == 0 ? 0 : (r1->ru_idrss+r1->ru_isrss-(r0->ru_idrss+r0->ru_isrss))/t));
00179                         break;
00180 
00181                 case 'K':
00182                         bu_vls_printf(vp, "%ld", (long)(t == 0 ? 0 :  ((r1->ru_ixrss+r1->ru_isrss+r1->ru_idrss) - (r0->ru_ixrss+r0->ru_idrss+r0->ru_isrss))/t));
00183                         break;
00184 
00185                 case 'M':
00186                         bu_vls_printf(vp, "%ld", (long)(r1->ru_maxrss/2));
00187                         break;
00188 
00189                 case 'F':
00190                         bu_vls_printf(vp, "%ld", (long)(r1->ru_majflt-r0->ru_majflt));
00191                         break;
00192 
00193                 case 'R':
00194                         bu_vls_printf(vp, "%ld", (long)(r1->ru_minflt-r0->ru_minflt));
00195                         break;
00196 
00197                 case 'I':
00198                         bu_vls_printf(vp, "%ld", (long)(r1->ru_inblock-r0->ru_inblock));
00199                         break;
00200 
00201                 case 'O':
00202                         bu_vls_printf(vp, "%ld", (long)(r1->ru_oublock-r0->ru_oublock));
00203                         break;
00204                 case 'C':
00205                         bu_vls_printf(vp, "%ld+%ld", (long)(r1->ru_nvcsw-r0->ru_nvcsw), (long)(r1->ru_nivcsw-r0->ru_nivcsw) );
00206                         break;
00207                 }
00208         }
00209 }
00210 
00211 #if 0
00212 static void
00213 tvadd(tsum, t0)
00214         struct timeval *tsum, *t0;
00215 {
00216 
00217         tsum->tv_sec += t0->tv_sec;
00218         tsum->tv_usec += t0->tv_usec;
00219         if (tsum->tv_usec > 1000000)
00220                 tsum->tv_sec++, tsum->tv_usec -= 1000000;
00221 }
00222 #endif
00223 
00224 static void
00225 tvsub(struct timeval *tdiff, struct timeval *t1, struct timeval *t0)
00226 {
00227 
00228         tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
00229         tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
00230         if (tdiff->tv_usec < 0)
00231                 tdiff->tv_sec--, tdiff->tv_usec += 1000000;
00232 }
00233 
00234 static void
00235 psecs(long int l, struct bu_vls *vp)
00236 {
00237         register int i;
00238 
00239         i = l / 3600;
00240         if (i) {
00241                 register int    j;
00242                 bu_vls_printf(vp, "%d:", i);
00243                 i = l % 3600;
00244                 j = i / 60;
00245                 bu_vls_printf(vp, "%d%d", j / 10, j % 10);
00246         } else {
00247                 i = l;
00248                 bu_vls_printf(vp, "%d", i / 60);
00249         }
00250         i = i % 60; /* GSM: bug in Alliant CE optimization prohibits "%=" here */
00251         bu_vls_printf(vp, ":%d%d", i / 10, i % 10);
00252 }
00253 
00254 /*
00255  *                      R T _ R E A D _ T I M E R
00256  *
00257  *  Compatability routine
00258  */
00259 double
00260 rt_read_timer(char *str, int len)
00261 {
00262         struct bu_vls   vls;
00263         double          cpu;
00264         int             todo;
00265 
00266         if( !str )  return  rt_get_timer( (struct bu_vls *)0, (double *)0 );
00267 
00268         bu_vls_init( &vls );
00269         cpu = rt_get_timer( &vls, (double *)0 );
00270         todo = bu_vls_strlen( &vls );
00271         if( todo > len )  todo = len-1;
00272         strncpy( str, bu_vls_addr(&vls), todo );
00273         str[todo] = '\0';
00274         return cpu;
00275 }
00276 
00277 /*@}*/
00278 /*
00279  * Local Variables:
00280  * mode: C
00281  * tab-width: 8
00282  * c-basic-offset: 4
00283  * indent-tabs-mode: t
00284  * End:
00285  * ex: shiftwidth=4 tabstop=8
00286  */

Generated on Mon Sep 18 01:24:57 2006 for BRL-CAD by  doxygen 1.4.6