0025907: Optimization of testdiff command
[occt.git] / src / OSD / OSD_PerfMeter.cxx
CommitLineData
b311480e 1/*
2 Created on: 2000-08-10
3 Created by: Michael SAZONOV
973c2be1 4 Copyright (c) 2000-2014 OPEN CASCADE SAS
b311480e 5
973c2be1 6 This file is part of Open CASCADE Technology software library.
b311480e 7
d5f74e42 8 This library is free software; you can redistribute it and/or modify it under
9 the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 10 by the Free Software Foundation, with special exception defined in the file
11 OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 distribution for complete text of the license and disclaimer of any warranty.
b311480e 13
973c2be1 14 Alternatively, this file may be used under the terms of Open CASCADE
15 commercial license or contractual agreement.
b311480e 16*/
17
18/*======================================================================
19*/
20/*Purpose : Set of functions to measure the CPU user time
21*/
22/*25/09/2001 : AGV : (const char *) in prototypes;
23*/
24/*09/11/2001 : AGV : Add functions perf_*_imeter for performance
25*/
26/*Add function perf_tick_meter
27*/
28/*14/05/2002 : AGV : Portability UNIX/Windows
29*/
30/*======================================================================*/
7fd59977 31#include <string.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <limits.h>
35#include <time.h>
c2ae831c 36#include <OSD_Chronometer.hxx>
7fd59977 37#include <OSD_PerfMeter.h>
38
7fd59977 39
40/*======================================================================
41 DEFINITIONS
42======================================================================*/
43
c2ae831c 44typedef Standard_Real PERF_TIME;
45
46#define PICK_TIME(_utime) { \
47 Standard_Real ktime; \
48 OSD_Chronometer::GetThreadCPU(_utime, ktime);\
49}
50
7fd59977 51typedef struct {
52 char* name; /* identifier */
53 PERF_TIME cumul_time; /* cumulative time */
54 PERF_TIME start_time; /* to store start time */
55 int nb_enter; /* number of enters */
56} t_TimeCounter;
57
58#define MAX_METERS 100
59
60static t_TimeCounter MeterTable[MAX_METERS];
61static int nb_meters = 0;
62
c2ae831c 63static int find_meter (const char * const MeterName);
64static int _perf_init_meter (const char * const MeterName,
7fd59977 65 const int doFind);
66
67/*======================================================================
68Function : perf_init_meter
69Purpose : Creates new counter (if it is absent) identified by
70 MeterName and resets its cumulative value
71Returns : iMeter if OK, -1 if alloc problem
72======================================================================*/
73int perf_init_meter (const char * const MeterName)
74{
75 return _perf_init_meter (MeterName, ~0);
76}
77
78/*======================================================================
79Function : perf_tick_meter
80Purpose : Increments the counter of meter MeterName without changing
81 its state with respect to measurement of time.
82 creates new meter if there is no such meter
83Returns : iMeter if OK, -1 if no such meter and cannot create a new one
84======================================================================*/
85int perf_tick_meter (const char * const MeterName)
86{
87 int ic = find_meter (MeterName);
88
89 if (ic == -1) {
90 /* create new meter */
91 ic = _perf_init_meter (MeterName, 0);
92 }
93
94 if (ic >= 0)
95 MeterTable[ic].nb_enter ++;
96
97 return ic;
98}
99
100/*======================================================================
101Function : perf_tick_imeter
102Purpose : Increments the counter of meter iMeter without changing
103 its state with respect to measurement of time.
104Returns : iMeter if OK, -1 if no such meter
105======================================================================*/
106int perf_tick_imeter (const int iMeter)
107{
108 if (iMeter >= 0 && iMeter < nb_meters) {
109 MeterTable[iMeter].nb_enter ++;
110 return iMeter;
111 }
112 return -1;
113}
114
115/*======================================================================
116Function : perf_start_meter
117Purpose : Forces meter MeterName to begin to count by remembering
118 the current data of timer;
119 creates new meter if there is no such meter
120Returns : iMeter if OK, -1 if no such meter and cannot create a new one
121======================================================================*/
122int perf_start_meter (const char * const MeterName)
123{
124 int ic = find_meter (MeterName);
125
126 if (ic == -1) {
127 /* create new meter */
128 ic = _perf_init_meter (MeterName, 0);
129 }
130
131 if (ic >= 0)
132 PICK_TIME (MeterTable[ic].start_time)
133
134 return ic;
135}
136
137/*======================================================================
138Function : perf_start_imeter
139Purpose : Forces meter with number iMeter to begin count by remembering
140 the current data of timer;
141 the meter must be previously created
142Returns : iMeter if OK, -1 if no such meter
143======================================================================*/
144int perf_start_imeter (const int iMeter)
145{
146 if (iMeter >= 0 && iMeter < nb_meters) {
147 PICK_TIME (MeterTable[iMeter].start_time)
148 return iMeter;
149 }
150 return -1;
151}
152
153/*======================================================================
154Function : perf_stop_meter
155Purpose : Forces meter MeterName to stop and cumulate time elapsed
156 since start
157Returns : iMeter if OK, -1 if no such meter or it is has not been started
158======================================================================*/
159int perf_stop_meter (const char * const MeterName)
160{
161 const int ic = find_meter (MeterName);
162
163 if (ic >= 0 && MeterTable[ic].start_time) {
164 t_TimeCounter * const ptc = &MeterTable[ic];
165 PERF_TIME utime;
166 PICK_TIME (utime)
167 ptc->cumul_time += utime - ptc->start_time;
168 ptc->start_time = 0;
169 ptc->nb_enter++;
170 }
171
172 return ic;
173}
174
175/*======================================================================
176Function : perf_stop_imeter
177Purpose : Forces meter with number iMeter to stop and cumulate the time
178 elapsed since the start
179Returns : iMeter if OK, -1 if no such meter or it is has not been started
180======================================================================*/
181int perf_stop_imeter (const int iMeter)
182{
183 if (iMeter >= 0 && iMeter < nb_meters) {
184 t_TimeCounter * const ptc = &MeterTable[iMeter];
185 if (ptc->start_time) {
186 PERF_TIME utime;
187 PICK_TIME (utime)
188 ptc->cumul_time += utime - ptc->start_time;
189 ptc->start_time = 0;
190 ptc->nb_enter++;
191 return iMeter;
192 }
193 }
194 return -1;
195}
196
197/*======================================================================
198Function : perf_get_meter
199Purpose : Tells the time cumulated by meter MeterName and the number
200 of enters to this meter
201Output : *nb_enter, *seconds if the pointers != NULL
202Returns : iMeter if OK, -1 if no such meter
203======================================================================*/
204int perf_get_meter (const char * const MeterName,
205 int * nb_enter,
206 double * seconds)
207{
208 const int ic = find_meter (MeterName);
209
210 if (ic >= 0) {
211 if (nb_enter) *nb_enter = MeterTable[ic].nb_enter;
c2ae831c 212 if (seconds) *seconds = MeterTable[ic].cumul_time;
7fd59977 213 }
214 return ic;
215}
216
217/*======================================================================
218Function : perf_print_all_meters
219Purpose : Prints on stdout the cumulated time and the number of
220 enters for each meter in MeterTable;
618617fe 221 resets all meters if reset is non-null
7fd59977 222======================================================================*/
618617fe 223void perf_print_all_meters (int reset)
7fd59977 224{
618617fe 225 char buffer[MAX_METERS * 256];
226 perf_sprint_all_meters (buffer, MAX_METERS * 256, reset);
227 printf ("%s", buffer);
228}
229
230/*======================================================================
231Function : perf_print_all_meters
232Purpose : Prints to string buffer the cumulated time and the number of
233 enters for each meter in MeterTable;
234 resets all meters if reset is non-null
235======================================================================*/
236void perf_sprint_all_meters (char *buffer, int length, int reset)
237{
238 char string[256];
239
7fd59977 240 int i;
241 for (i=0; i<nb_meters; i++) {
242 const t_TimeCounter * const ptc = &MeterTable[i];
243 if (ptc && ptc->nb_enter) {
936f43da 244 int n = sprintf (string, " Perf meter results : enters seconds microsec/enter\n");
618617fe 245 if (n < length)
246 {
247 memcpy (buffer, string, n);
248 buffer += n;
249 length -= n;
250 }
7fd59977 251 break;
252 }
253 }
254
255 while (i < nb_meters) {
256 t_TimeCounter * const ptc = &MeterTable[i++];
257
258 if (ptc && ptc->nb_enter) {
c2ae831c 259 const double secs = ptc->cumul_time;
7fd59977 260
618617fe 261 int n = 0;
7fd59977 262 if (ptc->start_time)
618617fe 263 n = sprintf (string, "Warning : meter %42s has not been stopped\n", ptc->name);
264
265 n += sprintf (string + n, "%-42s : %7d %8.2f %10.2f\n",
266 ptc->name, ptc->nb_enter, secs,
267 (secs>0. ? 1000000 * secs/ptc->nb_enter : 0.));
268 if (n < length)
269 {
270 memcpy (buffer, string, n);
271 buffer += n;
272 length -= n;
273 }
274
275 if (reset)
276 {
277 ptc->cumul_time = 0;
278 ptc->start_time = 0;
279 ptc->nb_enter = 0;
280 }
7fd59977 281 }
282 }
618617fe 283 *buffer = '\0';
7fd59977 284}
285
286/*======================================================================
287Function : perf_close_meter
288Purpose : Prints out a meter and resets it
289Returns : none
290======================================================================*/
291void perf_close_meter (const char * const MeterName)
292{
618617fe 293 perf_close_imeter (find_meter (MeterName));
7fd59977 294}
295
296/*======================================================================
297Function : perf_close_imeter
298Purpose : Prints out a meter and resets it
299Returns : none
300======================================================================*/
301void perf_close_imeter (const int iMeter)
302{
303 if (iMeter >= 0 && iMeter < nb_meters && MeterTable[iMeter].nb_enter) {
304 t_TimeCounter * const ptc = &MeterTable[iMeter];
305 if (ptc->start_time)
306 printf (" ===> Warning : meter %s has not been stopped\n", ptc->name);
307 printf (" ===> [%s] : %d enters, %9.3f seconds\n",
c2ae831c 308 ptc->name, ptc->nb_enter, ptc->cumul_time);
7fd59977 309 ptc->cumul_time = 0;
310 ptc->start_time = 0;
311 ptc->nb_enter = 0;
312 }
313}
314
315/*======================================================================
316Function : perf_destroy_all_meters
317Purpose : Deletes all meters and frees memory
318Returns : none
319======================================================================*/
320void perf_destroy_all_meters (void)
321{
322 int i;
323 for (i=0; i<nb_meters; i++)
324 free (MeterTable[i].name);
325 nb_meters = 0;
326}
327
328/* agv - non portable: #pragma fini (perf_print_and_destroy)
329 using atexit instead (see _perf_init_meter below) */
330
331void perf_print_and_destroy (void)
332{
618617fe 333 perf_print_all_meters (0);
7fd59977 334 perf_destroy_all_meters ();
335}
336
337/*======================================================================
338Function : _perf_init_meter
339Purpose : Creates new counter (if it is absent) identified by
340 MeterName and resets its cumulative value
341Returns : index of meter if OK, -1 if alloc problem
342Remarks : For internal use in this module
343======================================================================*/
344static int _perf_init_meter (const char * const MeterName,
345 const int doFind)
346{
347 static int hasbeencalled = 0;
348 int ic = -1;
349 if (doFind)
350 ic = find_meter (MeterName);
351
352 if (ic == -1) {
353 if (nb_meters >= MAX_METERS) return 0;
354 ic = nb_meters;
355
356 MeterTable[ic].name = strdup (MeterName);
357 if (!MeterTable[ic].name)
358 return -1;
359
360 nb_meters++;
361 }
362
363 MeterTable[ic].cumul_time = 0;
364 MeterTable[ic].start_time = 0;
365 MeterTable[ic].nb_enter = 0;
366 if (hasbeencalled == 0) {
367 atexit (perf_print_and_destroy);
368 hasbeencalled = ~0;
369 }
370 return ic;
371}
372
373/*======================================================================
374Function : find_meter
375Purpose : Finds the meter MeterName in the MeterTable
376Returns : Index of meter object, -1 if not found
377Remarks : For internal use in this module
378======================================================================*/
379static int find_meter (const char * const MeterName)
380{
381 int i;
382 for (i=0; i<nb_meters; i++)
383 if (!strcmp (MeterTable[i].name, MeterName)) return i;
384 return -1;
385}