3 Created by: Michael SAZONOV
4 Copyright (c) 2000-2014 OPEN CASCADE SAS
6 This file is part of Open CASCADE Technology software library.
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
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.
14 Alternatively, this file may be used under the terms of Open CASCADE
15 commercial license or contractual agreement.
18 /*======================================================================
20 /*Purpose : Set of functions to measure the CPU user time
22 /*25/09/2001 : AGV : (const char *) in prototypes;
24 /*09/11/2001 : AGV : Add functions perf_*_imeter for performance
26 /*Add function perf_tick_meter
28 /*14/05/2002 : AGV : Portability UNIX/Windows
30 /*======================================================================*/
36 #include <OSD_Chronometer.hxx>
37 #include <OSD_PerfMeter.h>
40 /*======================================================================
42 ======================================================================*/
44 typedef Standard_Real PERF_TIME;
46 #define PICK_TIME(_utime) { \
47 Standard_Real ktime; \
48 OSD_Chronometer::GetThreadCPU(_utime, ktime);\
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 */
58 #define MAX_METERS 100
60 static t_TimeCounter MeterTable[MAX_METERS];
61 static int nb_meters = 0;
63 static int find_meter (const char * const MeterName);
64 static int _perf_init_meter (const char * const MeterName,
67 /*======================================================================
68 Function : perf_init_meter
69 Purpose : Creates new counter (if it is absent) identified by
70 MeterName and resets its cumulative value
71 Returns : iMeter if OK, -1 if alloc problem
72 ======================================================================*/
73 int perf_init_meter (const char * const MeterName)
75 return _perf_init_meter (MeterName, ~0);
78 /*======================================================================
79 Function : perf_tick_meter
80 Purpose : 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
83 Returns : iMeter if OK, -1 if no such meter and cannot create a new one
84 ======================================================================*/
85 int perf_tick_meter (const char * const MeterName)
87 int ic = find_meter (MeterName);
90 /* create new meter */
91 ic = _perf_init_meter (MeterName, 0);
95 MeterTable[ic].nb_enter ++;
100 /*======================================================================
101 Function : perf_tick_imeter
102 Purpose : Increments the counter of meter iMeter without changing
103 its state with respect to measurement of time.
104 Returns : iMeter if OK, -1 if no such meter
105 ======================================================================*/
106 int perf_tick_imeter (const int iMeter)
108 if (iMeter >= 0 && iMeter < nb_meters) {
109 MeterTable[iMeter].nb_enter ++;
115 /*======================================================================
116 Function : perf_start_meter
117 Purpose : 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
120 Returns : iMeter if OK, -1 if no such meter and cannot create a new one
121 ======================================================================*/
122 int perf_start_meter (const char * const MeterName)
124 int ic = find_meter (MeterName);
127 /* create new meter */
128 ic = _perf_init_meter (MeterName, 0);
132 PICK_TIME (MeterTable[ic].start_time)
137 /*======================================================================
138 Function : perf_start_imeter
139 Purpose : Forces meter with number iMeter to begin count by remembering
140 the current data of timer;
141 the meter must be previously created
142 Returns : iMeter if OK, -1 if no such meter
143 ======================================================================*/
144 int perf_start_imeter (const int iMeter)
146 if (iMeter >= 0 && iMeter < nb_meters) {
147 PICK_TIME (MeterTable[iMeter].start_time)
153 /*======================================================================
154 Function : perf_stop_meter
155 Purpose : Forces meter MeterName to stop and cumulate time elapsed
157 Returns : iMeter if OK, -1 if no such meter or it is has not been started
158 ======================================================================*/
159 int perf_stop_meter (const char * const MeterName)
161 const int ic = find_meter (MeterName);
163 if (ic >= 0 && MeterTable[ic].start_time) {
164 t_TimeCounter * const ptc = &MeterTable[ic];
167 ptc->cumul_time += utime - ptc->start_time;
175 /*======================================================================
176 Function : perf_stop_imeter
177 Purpose : Forces meter with number iMeter to stop and cumulate the time
178 elapsed since the start
179 Returns : iMeter if OK, -1 if no such meter or it is has not been started
180 ======================================================================*/
181 int perf_stop_imeter (const int iMeter)
183 if (iMeter >= 0 && iMeter < nb_meters) {
184 t_TimeCounter * const ptc = &MeterTable[iMeter];
185 if (ptc->start_time) {
188 ptc->cumul_time += utime - ptc->start_time;
197 /*======================================================================
198 Function : perf_get_meter
199 Purpose : Tells the time cumulated by meter MeterName and the number
200 of enters to this meter
201 Output : *nb_enter, *seconds if the pointers != NULL
202 Returns : iMeter if OK, -1 if no such meter
203 ======================================================================*/
204 int perf_get_meter (const char * const MeterName,
208 const int ic = find_meter (MeterName);
211 if (nb_enter) *nb_enter = MeterTable[ic].nb_enter;
212 if (seconds) *seconds = MeterTable[ic].cumul_time;
217 /*======================================================================
218 Function : perf_print_all_meters
219 Purpose : Prints on stdout the cumulated time and the number of
220 enters for each meter in MeterTable;
221 resets all meters if reset is non-null
222 ======================================================================*/
223 void perf_print_all_meters (int reset)
225 char buffer[MAX_METERS * 256];
226 perf_sprint_all_meters (buffer, MAX_METERS * 256, reset);
227 printf ("%s", buffer);
230 /*======================================================================
231 Function : perf_print_all_meters
232 Purpose : 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 ======================================================================*/
236 void perf_sprint_all_meters (char *buffer, int length, int reset)
241 for (i=0; i<nb_meters; i++) {
242 const t_TimeCounter * const ptc = &MeterTable[i];
243 if (ptc && ptc->nb_enter) {
244 int n = sprintf (string, " Perf meter results : enters seconds microsec/enter\n");
247 memcpy (buffer, string, n);
255 while (i < nb_meters) {
256 t_TimeCounter * const ptc = &MeterTable[i++];
258 if (ptc && ptc->nb_enter) {
259 const double secs = ptc->cumul_time;
263 n = sprintf (string, "Warning : meter %42s has not been stopped\n", ptc->name);
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.));
270 memcpy (buffer, string, n);
286 /*======================================================================
287 Function : perf_close_meter
288 Purpose : Prints out a meter and resets it
290 ======================================================================*/
291 void perf_close_meter (const char * const MeterName)
293 perf_close_imeter (find_meter (MeterName));
296 /*======================================================================
297 Function : perf_close_imeter
298 Purpose : Prints out a meter and resets it
300 ======================================================================*/
301 void perf_close_imeter (const int iMeter)
303 if (iMeter >= 0 && iMeter < nb_meters && MeterTable[iMeter].nb_enter) {
304 t_TimeCounter * const ptc = &MeterTable[iMeter];
306 printf (" ===> Warning : meter %s has not been stopped\n", ptc->name);
307 printf (" ===> [%s] : %d enters, %9.3f seconds\n",
308 ptc->name, ptc->nb_enter, ptc->cumul_time);
315 /*======================================================================
316 Function : perf_destroy_all_meters
317 Purpose : Deletes all meters and frees memory
319 ======================================================================*/
320 void perf_destroy_all_meters (void)
323 for (i=0; i<nb_meters; i++)
324 free (MeterTable[i].name);
328 /* agv - non portable: #pragma fini (perf_print_and_destroy)
329 using atexit instead (see _perf_init_meter below) */
331 void perf_print_and_destroy (void)
333 perf_print_all_meters (0);
334 perf_destroy_all_meters ();
337 /*======================================================================
338 Function : _perf_init_meter
339 Purpose : Creates new counter (if it is absent) identified by
340 MeterName and resets its cumulative value
341 Returns : index of meter if OK, -1 if alloc problem
342 Remarks : For internal use in this module
343 ======================================================================*/
344 static int _perf_init_meter (const char * const MeterName,
347 static int hasbeencalled = 0;
350 ic = find_meter (MeterName);
353 if (nb_meters >= MAX_METERS) return 0;
356 MeterTable[ic].name = strdup (MeterName);
357 if (!MeterTable[ic].name)
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);
373 /*======================================================================
374 Function : find_meter
375 Purpose : Finds the meter MeterName in the MeterTable
376 Returns : Index of meter object, -1 if not found
377 Remarks : For internal use in this module
378 ======================================================================*/
379 static int find_meter (const char * const MeterName)
382 for (i=0; i<nb_meters; i++)
383 if (!strcmp (MeterTable[i].name, MeterName)) return i;