mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-05 18:16:23 +03:00
- Work with strings optimized in Tcl procedures used in testdiff command - CPU and memory differences output of testdiff command improved to give relative change in percents - Cumulative CPU and memory differences are output for test grids - In HTML output of testdiff command, deviations of memory and CPU measurements greater than 5% are colored (red or green) - Search of image files in testdiff command corrected to avoid wrong attribution of image file to issues starting with the same first letters; images must start with the test case name, optionally followed by underscore or dash and arbitrary text - Image_Diff tool optimized for the case if images are exactly the same - Perf_Meter class output corrected, destructor made non-virtual - DRAW command diffimage optimized to not save diff files if there is no difference - Tests User Guide updated according to these changes and actual state
386 lines
12 KiB
C++
386 lines
12 KiB
C++
/*
|
|
Created on: 2000-08-10
|
|
Created by: Michael SAZONOV
|
|
Copyright (c) 2000-2014 OPEN CASCADE SAS
|
|
|
|
This file is part of Open CASCADE Technology software library.
|
|
|
|
This library is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU Lesser General Public License version 2.1 as published
|
|
by the Free Software Foundation, with special exception defined in the file
|
|
OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
|
distribution for complete text of the license and disclaimer of any warranty.
|
|
|
|
Alternatively, this file may be used under the terms of Open CASCADE
|
|
commercial license or contractual agreement.
|
|
*/
|
|
|
|
/*======================================================================
|
|
*/
|
|
/*Purpose : Set of functions to measure the CPU user time
|
|
*/
|
|
/*25/09/2001 : AGV : (const char *) in prototypes;
|
|
*/
|
|
/*09/11/2001 : AGV : Add functions perf_*_imeter for performance
|
|
*/
|
|
/*Add function perf_tick_meter
|
|
*/
|
|
/*14/05/2002 : AGV : Portability UNIX/Windows
|
|
*/
|
|
/*======================================================================*/
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <limits.h>
|
|
#include <time.h>
|
|
#include <OSD_Chronometer.hxx>
|
|
#include <OSD_PerfMeter.h>
|
|
|
|
|
|
/*======================================================================
|
|
DEFINITIONS
|
|
======================================================================*/
|
|
|
|
typedef Standard_Real PERF_TIME;
|
|
|
|
#define PICK_TIME(_utime) { \
|
|
Standard_Real ktime; \
|
|
OSD_Chronometer::GetThreadCPU(_utime, ktime);\
|
|
}
|
|
|
|
typedef struct {
|
|
char* name; /* identifier */
|
|
PERF_TIME cumul_time; /* cumulative time */
|
|
PERF_TIME start_time; /* to store start time */
|
|
int nb_enter; /* number of enters */
|
|
} t_TimeCounter;
|
|
|
|
#define MAX_METERS 100
|
|
|
|
static t_TimeCounter MeterTable[MAX_METERS];
|
|
static int nb_meters = 0;
|
|
|
|
static int find_meter (const char * const MeterName);
|
|
static int _perf_init_meter (const char * const MeterName,
|
|
const int doFind);
|
|
|
|
/*======================================================================
|
|
Function : perf_init_meter
|
|
Purpose : Creates new counter (if it is absent) identified by
|
|
MeterName and resets its cumulative value
|
|
Returns : iMeter if OK, -1 if alloc problem
|
|
======================================================================*/
|
|
int perf_init_meter (const char * const MeterName)
|
|
{
|
|
return _perf_init_meter (MeterName, ~0);
|
|
}
|
|
|
|
/*======================================================================
|
|
Function : perf_tick_meter
|
|
Purpose : Increments the counter of meter MeterName without changing
|
|
its state with respect to measurement of time.
|
|
creates new meter if there is no such meter
|
|
Returns : iMeter if OK, -1 if no such meter and cannot create a new one
|
|
======================================================================*/
|
|
int perf_tick_meter (const char * const MeterName)
|
|
{
|
|
int ic = find_meter (MeterName);
|
|
|
|
if (ic == -1) {
|
|
/* create new meter */
|
|
ic = _perf_init_meter (MeterName, 0);
|
|
}
|
|
|
|
if (ic >= 0)
|
|
MeterTable[ic].nb_enter ++;
|
|
|
|
return ic;
|
|
}
|
|
|
|
/*======================================================================
|
|
Function : perf_tick_imeter
|
|
Purpose : Increments the counter of meter iMeter without changing
|
|
its state with respect to measurement of time.
|
|
Returns : iMeter if OK, -1 if no such meter
|
|
======================================================================*/
|
|
int perf_tick_imeter (const int iMeter)
|
|
{
|
|
if (iMeter >= 0 && iMeter < nb_meters) {
|
|
MeterTable[iMeter].nb_enter ++;
|
|
return iMeter;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*======================================================================
|
|
Function : perf_start_meter
|
|
Purpose : Forces meter MeterName to begin to count by remembering
|
|
the current data of timer;
|
|
creates new meter if there is no such meter
|
|
Returns : iMeter if OK, -1 if no such meter and cannot create a new one
|
|
======================================================================*/
|
|
int perf_start_meter (const char * const MeterName)
|
|
{
|
|
int ic = find_meter (MeterName);
|
|
|
|
if (ic == -1) {
|
|
/* create new meter */
|
|
ic = _perf_init_meter (MeterName, 0);
|
|
}
|
|
|
|
if (ic >= 0)
|
|
PICK_TIME (MeterTable[ic].start_time)
|
|
|
|
return ic;
|
|
}
|
|
|
|
/*======================================================================
|
|
Function : perf_start_imeter
|
|
Purpose : Forces meter with number iMeter to begin count by remembering
|
|
the current data of timer;
|
|
the meter must be previously created
|
|
Returns : iMeter if OK, -1 if no such meter
|
|
======================================================================*/
|
|
int perf_start_imeter (const int iMeter)
|
|
{
|
|
if (iMeter >= 0 && iMeter < nb_meters) {
|
|
PICK_TIME (MeterTable[iMeter].start_time)
|
|
return iMeter;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*======================================================================
|
|
Function : perf_stop_meter
|
|
Purpose : Forces meter MeterName to stop and cumulate time elapsed
|
|
since start
|
|
Returns : iMeter if OK, -1 if no such meter or it is has not been started
|
|
======================================================================*/
|
|
int perf_stop_meter (const char * const MeterName)
|
|
{
|
|
const int ic = find_meter (MeterName);
|
|
|
|
if (ic >= 0 && MeterTable[ic].start_time) {
|
|
t_TimeCounter * const ptc = &MeterTable[ic];
|
|
PERF_TIME utime;
|
|
PICK_TIME (utime)
|
|
ptc->cumul_time += utime - ptc->start_time;
|
|
ptc->start_time = 0;
|
|
ptc->nb_enter++;
|
|
}
|
|
|
|
return ic;
|
|
}
|
|
|
|
/*======================================================================
|
|
Function : perf_stop_imeter
|
|
Purpose : Forces meter with number iMeter to stop and cumulate the time
|
|
elapsed since the start
|
|
Returns : iMeter if OK, -1 if no such meter or it is has not been started
|
|
======================================================================*/
|
|
int perf_stop_imeter (const int iMeter)
|
|
{
|
|
if (iMeter >= 0 && iMeter < nb_meters) {
|
|
t_TimeCounter * const ptc = &MeterTable[iMeter];
|
|
if (ptc->start_time) {
|
|
PERF_TIME utime;
|
|
PICK_TIME (utime)
|
|
ptc->cumul_time += utime - ptc->start_time;
|
|
ptc->start_time = 0;
|
|
ptc->nb_enter++;
|
|
return iMeter;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*======================================================================
|
|
Function : perf_get_meter
|
|
Purpose : Tells the time cumulated by meter MeterName and the number
|
|
of enters to this meter
|
|
Output : *nb_enter, *seconds if the pointers != NULL
|
|
Returns : iMeter if OK, -1 if no such meter
|
|
======================================================================*/
|
|
int perf_get_meter (const char * const MeterName,
|
|
int * nb_enter,
|
|
double * seconds)
|
|
{
|
|
const int ic = find_meter (MeterName);
|
|
|
|
if (ic >= 0) {
|
|
if (nb_enter) *nb_enter = MeterTable[ic].nb_enter;
|
|
if (seconds) *seconds = MeterTable[ic].cumul_time;
|
|
}
|
|
return ic;
|
|
}
|
|
|
|
/*======================================================================
|
|
Function : perf_print_all_meters
|
|
Purpose : Prints on stdout the cumulated time and the number of
|
|
enters for each meter in MeterTable;
|
|
resets all meters if reset is non-null
|
|
======================================================================*/
|
|
void perf_print_all_meters (int reset)
|
|
{
|
|
char buffer[MAX_METERS * 256];
|
|
perf_sprint_all_meters (buffer, MAX_METERS * 256, reset);
|
|
printf ("%s", buffer);
|
|
}
|
|
|
|
/*======================================================================
|
|
Function : perf_print_all_meters
|
|
Purpose : Prints to string buffer the cumulated time and the number of
|
|
enters for each meter in MeterTable;
|
|
resets all meters if reset is non-null
|
|
======================================================================*/
|
|
void perf_sprint_all_meters (char *buffer, int length, int reset)
|
|
{
|
|
char string[256];
|
|
|
|
int i;
|
|
for (i=0; i<nb_meters; i++) {
|
|
const t_TimeCounter * const ptc = &MeterTable[i];
|
|
if (ptc && ptc->nb_enter) {
|
|
int n = sprintf (string, " Perf meter results : enters seconds microsec/enter\n");
|
|
if (n < length)
|
|
{
|
|
memcpy (buffer, string, n);
|
|
buffer += n;
|
|
length -= n;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
while (i < nb_meters) {
|
|
t_TimeCounter * const ptc = &MeterTable[i++];
|
|
|
|
if (ptc && ptc->nb_enter) {
|
|
const double secs = ptc->cumul_time;
|
|
|
|
int n = 0;
|
|
if (ptc->start_time)
|
|
n = sprintf (string, "Warning : meter %42s has not been stopped\n", ptc->name);
|
|
|
|
n += sprintf (string + n, "%-42s : %7d %8.2f %10.2f\n",
|
|
ptc->name, ptc->nb_enter, secs,
|
|
(secs>0. ? 1000000 * secs/ptc->nb_enter : 0.));
|
|
if (n < length)
|
|
{
|
|
memcpy (buffer, string, n);
|
|
buffer += n;
|
|
length -= n;
|
|
}
|
|
|
|
if (reset)
|
|
{
|
|
ptc->cumul_time = 0;
|
|
ptc->start_time = 0;
|
|
ptc->nb_enter = 0;
|
|
}
|
|
}
|
|
}
|
|
*buffer = '\0';
|
|
}
|
|
|
|
/*======================================================================
|
|
Function : perf_close_meter
|
|
Purpose : Prints out a meter and resets it
|
|
Returns : none
|
|
======================================================================*/
|
|
void perf_close_meter (const char * const MeterName)
|
|
{
|
|
perf_close_imeter (find_meter (MeterName));
|
|
}
|
|
|
|
/*======================================================================
|
|
Function : perf_close_imeter
|
|
Purpose : Prints out a meter and resets it
|
|
Returns : none
|
|
======================================================================*/
|
|
void perf_close_imeter (const int iMeter)
|
|
{
|
|
if (iMeter >= 0 && iMeter < nb_meters && MeterTable[iMeter].nb_enter) {
|
|
t_TimeCounter * const ptc = &MeterTable[iMeter];
|
|
if (ptc->start_time)
|
|
printf (" ===> Warning : meter %s has not been stopped\n", ptc->name);
|
|
printf (" ===> [%s] : %d enters, %9.3f seconds\n",
|
|
ptc->name, ptc->nb_enter, ptc->cumul_time);
|
|
ptc->cumul_time = 0;
|
|
ptc->start_time = 0;
|
|
ptc->nb_enter = 0;
|
|
}
|
|
}
|
|
|
|
/*======================================================================
|
|
Function : perf_destroy_all_meters
|
|
Purpose : Deletes all meters and frees memory
|
|
Returns : none
|
|
======================================================================*/
|
|
void perf_destroy_all_meters (void)
|
|
{
|
|
int i;
|
|
for (i=0; i<nb_meters; i++)
|
|
free (MeterTable[i].name);
|
|
nb_meters = 0;
|
|
}
|
|
|
|
/* agv - non portable: #pragma fini (perf_print_and_destroy)
|
|
using atexit instead (see _perf_init_meter below) */
|
|
|
|
void perf_print_and_destroy (void)
|
|
{
|
|
perf_print_all_meters (0);
|
|
perf_destroy_all_meters ();
|
|
}
|
|
|
|
/*======================================================================
|
|
Function : _perf_init_meter
|
|
Purpose : Creates new counter (if it is absent) identified by
|
|
MeterName and resets its cumulative value
|
|
Returns : index of meter if OK, -1 if alloc problem
|
|
Remarks : For internal use in this module
|
|
======================================================================*/
|
|
static int _perf_init_meter (const char * const MeterName,
|
|
const int doFind)
|
|
{
|
|
static int hasbeencalled = 0;
|
|
int ic = -1;
|
|
if (doFind)
|
|
ic = find_meter (MeterName);
|
|
|
|
if (ic == -1) {
|
|
if (nb_meters >= MAX_METERS) return 0;
|
|
ic = nb_meters;
|
|
|
|
MeterTable[ic].name = strdup (MeterName);
|
|
if (!MeterTable[ic].name)
|
|
return -1;
|
|
|
|
nb_meters++;
|
|
}
|
|
|
|
MeterTable[ic].cumul_time = 0;
|
|
MeterTable[ic].start_time = 0;
|
|
MeterTable[ic].nb_enter = 0;
|
|
if (hasbeencalled == 0) {
|
|
atexit (perf_print_and_destroy);
|
|
hasbeencalled = ~0;
|
|
}
|
|
return ic;
|
|
}
|
|
|
|
/*======================================================================
|
|
Function : find_meter
|
|
Purpose : Finds the meter MeterName in the MeterTable
|
|
Returns : Index of meter object, -1 if not found
|
|
Remarks : For internal use in this module
|
|
======================================================================*/
|
|
static int find_meter (const char * const MeterName)
|
|
{
|
|
int i;
|
|
for (i=0; i<nb_meters; i++)
|
|
if (!strcmp (MeterTable[i].name, MeterName)) return i;
|
|
return -1;
|
|
}
|