BRL-CAD
timer42.c
Go to the documentation of this file.
1 /* T I M E R 4 2 . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1985-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 
21 #include "common.h"
22 
23 #include <stdio.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <sys/resource.h>
27 
28 #ifdef HAVE_SYS_TIME_H
29 # include <sys/time.h>
30 #endif
31 
32 
33 
34 #include "vmath.h"
35 #include "raytrace.h"
36 
37 static struct timeval time0; /* Time at which timing started */
38 static struct rusage ru0; /* Resource utilization at the start */
39 static struct rusage ru0c; /* Resource utilization at the start */
40 
41 static void prusage(register struct rusage *r0, register struct rusage *r1, struct timeval *e, struct timeval *b, struct bu_vls *vp);
42 static void tvsub(struct timeval *tdiff, struct timeval *t1, struct timeval *t0);
43 static void psecs(long int l, struct bu_vls *vp);
44 
45 
46 void
48 {
49  gettimeofday(&time0, (struct timezone *)0);
50  getrusage(RUSAGE_SELF, &ru0);
51  getrusage(RUSAGE_CHILDREN, &ru0c);
52 }
53 
54 
55 double
56 rt_get_timer(struct bu_vls *vp, double *elapsed)
57 {
58  struct timeval timedol;
59  struct rusage ru1;
60  struct rusage ru1c;
61  struct timeval td;
62  double user_cpu_secs;
63  double elapsed_secs;
64 
65 
66  getrusage(RUSAGE_SELF, &ru1);
67  getrusage(RUSAGE_CHILDREN, &ru1c);
68  gettimeofday(&timedol, (struct timezone *)0);
69 
70  elapsed_secs = (timedol.tv_sec - time0.tv_sec) +
71  (timedol.tv_usec - time0.tv_usec)/1000000.0;
72 
73  tvsub(&td, &ru1.ru_utime, &ru0.ru_utime);
74  user_cpu_secs = td.tv_sec + ((double)td.tv_usec) / 1000000.0;
75 
76  tvsub(&td, &ru1c.ru_utime, &ru0c.ru_utime);
77  user_cpu_secs += td.tv_sec + ((double)td.tv_usec) / 1000000.0;
78 
79  if (user_cpu_secs < 0.00001) user_cpu_secs = 0.00001;
80  if (elapsed_secs < 0.00001) elapsed_secs = user_cpu_secs; /* It can't be any less! */
81 
82  if (elapsed) *elapsed = elapsed_secs;
83 
84  if (vp) {
85  bu_vls_printf(vp, "cpu = %g sec, elapsed = %g sec\n",
86  user_cpu_secs, elapsed_secs);
87  bu_vls_strcat(vp, " parent: ");
88  prusage(&ru0, &ru1, &timedol, &time0, vp);
89  bu_vls_strcat(vp, "\n children: ");
90  prusage(&ru0c, &ru1c, &timedol, &time0, vp);
91  }
92 
93  return user_cpu_secs;
94 }
95 
96 
97 static void
98 prusage(register struct rusage *r0, register struct rusage *r1, struct timeval *e, struct timeval *b, struct bu_vls *vp)
99 {
100  struct timeval tdiff;
101  register time_t t;
102  register char *cp;
103  register int i;
104  int ms;
105 
106  BU_CK_VLS(vp);
107 
108  t = (r1->ru_utime.tv_sec-r0->ru_utime.tv_sec)*100+
109  (r1->ru_utime.tv_usec-r0->ru_utime.tv_usec)/10000+
110  (r1->ru_stime.tv_sec-r0->ru_stime.tv_sec)*100+
111  (r1->ru_stime.tv_usec-r0->ru_stime.tv_usec)/10000;
112  ms = (e->tv_sec-b->tv_sec)*100 + (e->tv_usec-b->tv_usec)/10000;
113 
114  cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw";
115  for (; *cp; cp++) {
116  if (*cp != '%')
117  bu_vls_putc(vp, *cp);
118  else if (cp[1]) switch (*++cp) {
119 
120  case 'U':
121  tvsub(&tdiff, &r1->ru_utime, &r0->ru_utime);
122  bu_vls_printf(vp, "%ld.%01ld", (long)tdiff.tv_sec, (long)(tdiff.tv_usec/100000));
123  break;
124 
125  case 'S':
126  tvsub(&tdiff, &r1->ru_stime, &r0->ru_stime);
127  bu_vls_printf(vp, "%ld.%01ld", (long)tdiff.tv_sec, (long)(tdiff.tv_usec/100000));
128  break;
129 
130  case 'E':
131  psecs(ms / 100, vp);
132  break;
133 
134  case 'P':
135  bu_vls_printf(vp, "%d%%", (int) (t*100 / ((ms ? ms : 1))));
136  break;
137 
138  case 'W':
139  i = r1->ru_nswap - r0->ru_nswap;
140  bu_vls_printf(vp, "%d", i);
141  break;
142 
143  case 'X':
144  bu_vls_printf(vp, "%ld", (long)(t == 0 ? 0 : (r1->ru_ixrss-r0->ru_ixrss)/t));
145  break;
146 
147  case 'D':
148  bu_vls_printf(vp, "%ld", (long)(t == 0 ? 0 : (r1->ru_idrss+r1->ru_isrss-(r0->ru_idrss+r0->ru_isrss))/t));
149  break;
150 
151  case 'K':
152  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));
153  break;
154 
155  case 'M':
156  bu_vls_printf(vp, "%ld", (long)(r1->ru_maxrss/2));
157  break;
158 
159  case 'F':
160  bu_vls_printf(vp, "%ld", (long)(r1->ru_majflt-r0->ru_majflt));
161  break;
162 
163  case 'R':
164  bu_vls_printf(vp, "%ld", (long)(r1->ru_minflt-r0->ru_minflt));
165  break;
166 
167  case 'I':
168  bu_vls_printf(vp, "%ld", (long)(r1->ru_inblock-r0->ru_inblock));
169  break;
170 
171  case 'O':
172  bu_vls_printf(vp, "%ld", (long)(r1->ru_oublock-r0->ru_oublock));
173  break;
174  case 'C':
175  bu_vls_printf(vp, "%ld+%ld", (long)(r1->ru_nvcsw-r0->ru_nvcsw), (long)(r1->ru_nivcsw-r0->ru_nivcsw));
176  break;
177  }
178  }
179 }
180 
181 
182 static void
183 tvsub(struct timeval *tdiff, struct timeval *t1, struct timeval *t0)
184 {
185 
186  tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
187  tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
188  if (tdiff->tv_usec < 0)
189  tdiff->tv_sec--, tdiff->tv_usec += 1000000;
190 }
191 
192 
193 static void
194 psecs(long int l, struct bu_vls *vp)
195 {
196  register int i;
197 
198  i = l / 3600;
199  if (i) {
200  register int j;
201  bu_vls_printf(vp, "%d:", i);
202  i = l % 3600;
203  j = i / 60;
204  bu_vls_printf(vp, "%d%d", j / 10, j % 10);
205  } else {
206  i = l;
207  bu_vls_printf(vp, "%d", i / 60);
208  }
209  i = i % 60;
210  bu_vls_printf(vp, ":%d%d", i / 10, i % 10);
211 }
212 
213 
214 double
215 rt_read_timer(char *str, int len)
216 {
217  struct bu_vls vls = BU_VLS_INIT_ZERO;
218  double cpu;
219  int todo;
220 
221  if (!str)
222  return rt_get_timer((struct bu_vls *)0, (double *)0);
223 
224  cpu = rt_get_timer(&vls, (double *)0);
225  todo = bu_vls_strlen(&vls);
226 
227  if (todo > len)
228  todo = len;
229  bu_strlcpy(str, bu_vls_addr(&vls), todo);
230 
231  return cpu;
232 }
233 
234 
235 /*
236  * Local Variables:
237  * mode: C
238  * tab-width: 8
239  * indent-tabs-mode: t
240  * c-file-style: "stroustrup"
241  * End:
242  * ex: shiftwidth=4 tabstop=8
243  */
void bu_vls_strcat(struct bu_vls *vp, const char *s)
Definition: vls.c:368
Header file for the BRL-CAD common definitions.
double rt_read_timer(char *str, int len)
Definition: timer42.c:215
double rt_get_timer(struct bu_vls *vp, double *elapsed)
Definition: timer42.c:56
#define BU_CK_VLS(_vp)
Definition: vls.h:69
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
time_t time0
Definition: timer-nt.c:32
size_t bu_vls_strlen(const struct bu_vls *vp)
Definition: vls.c:189
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
Definition: vls.h:56
void rt_prep_timer(void)
Definition: timer42.c:47
void bu_vls_putc(struct bu_vls *vp, int c)
Definition: vls.c:666