You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

294 lines
7.7 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkTimerLog.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/**
* @class vtkTimerLog
* @brief Timer support and logging
*
* vtkTimerLog contains walltime and cputime measurements associated
* with a given event. These results can be later analyzed when
* "dumping out" the table.
*
* In addition, vtkTimerLog allows the user to simply get the current
* time, and to start/stop a simple timer separate from the timing
* table logging.
*/
#ifndef vtkTimerLog_h
#define vtkTimerLog_h
#include "vtkCommonSystemModule.h" // For export macro
#include "vtkObject.h"
#include <string> // STL Header
#include <vector> // STL Header
#ifdef _WIN32
#include <sys/timeb.h> // Needed for Win32 implementation of timer
#include <sys/types.h> // Needed for Win32 implementation of timer
#else
#include <sys/time.h> // Needed for unix implementation of timer
#include <sys/times.h> // Needed for unix implementation of timer
#include <sys/types.h> // Needed for unix implementation of timer
#include <time.h> // Needed for unix implementation of timer
#endif
// var args
#ifndef _WIN32
#include <unistd.h> // Needed for unix implementation of timer
#endif
// select stuff here is for sleep method
#ifndef NO_FD_SET
#define SELECT_MASK fd_set
#else
#ifndef _AIX
typedef long fd_mask;
#endif
#if defined(_IBMR2)
#define SELECT_MASK void
#else
#define SELECT_MASK int
#endif
#endif
struct vtkTimerLogEntry
{
enum LogEntryType
{
INVALID = -1,
STANDALONE, // an individual, marked event
START, // start of a timed event
END, // end of a timed event
INSERTED // externally timed value
};
double WallTime;
int CpuTicks;
std::string Event;
LogEntryType Type;
unsigned char Indent;
vtkTimerLogEntry()
: WallTime(0)
, CpuTicks(0)
, Type(INVALID)
, Indent(0)
{
}
};
class VTKCOMMONSYSTEM_EXPORT vtkTimerLog : public vtkObject
{
public:
static vtkTimerLog* New();
vtkTypeMacro(vtkTimerLog, vtkObject);
void PrintSelf(ostream& os, vtkIndent indent) override;
/**
* This flag will turn logging of events off or on.
* By default, logging is on.
*/
static void SetLogging(int v) { vtkTimerLog::Logging = v; }
static int GetLogging() { return vtkTimerLog::Logging; }
static void LoggingOn() { vtkTimerLog::SetLogging(1); }
static void LoggingOff() { vtkTimerLog::SetLogging(0); }
//@{
/**
* Set/Get the maximum number of entries allowed in the timer log
*/
static void SetMaxEntries(int a);
static int GetMaxEntries();
//@}
/**
* Record a timing event. The event is represented by a formatted
* string. The internal buffer is 4096 bytes and will truncate anything longer.
*/
#ifndef __VTK_WRAP__
static void FormatAndMarkEvent(const char* EventString, ...) VTK_FORMAT_PRINTF(1, 2);
#endif
//@{
/**
* Write the timing table out to a file. Calculate some helpful
* statistics (deltas and percentages) in the process.
*/
static void DumpLog(const char* filename);
//@}
//@{
/**
* I want to time events, so I am creating this interface to
* mark events that have a start and an end. These events can be,
* nested. The standard Dumplog ignores the indents.
*/
static void MarkStartEvent(const char* EventString);
static void MarkEndEvent(const char* EventString);
//@}
//@{
/**
* Insert an event with a known wall time value (in seconds)
* and cpuTicks.
*/
static void InsertTimedEvent(const char* EventString, double time, int cpuTicks);
//@}
static void DumpLogWithIndents(ostream* os, double threshold);
static void DumpLogWithIndentsAndPercentages(ostream* os);
//@{
/**
* Programmatic access to events. Indexed from 0 to num-1.
*/
static int GetNumberOfEvents();
static int GetEventIndent(int i);
static double GetEventWallTime(int i);
static const char* GetEventString(int i);
static vtkTimerLogEntry::LogEntryType GetEventType(int i);
//@}
/**
* Record a timing event and capture wall time and cpu ticks.
*/
static void MarkEvent(const char* EventString);
/**
* Clear the timing table. walltime and cputime will also be set
* to zero when the first new event is recorded.
*/
static void ResetLog();
/**
* Remove timer log.
*/
static void CleanupLog();
/**
* Returns the elapsed number of seconds since 00:00:00 Coordinated Universal
* Time (UTC), Thursday, 1 January 1970. This is also called Unix Time.
*/
static double GetUniversalTime();
/**
* Returns the CPU time for this process
* On Win32 platforms this actually returns wall time.
*/
static double GetCPUTime();
/**
* Set the StartTime to the current time. Used with GetElapsedTime().
*/
void StartTimer();
/**
* Sets EndTime to the current time. Used with GetElapsedTime().
*/
void StopTimer();
/**
* Returns the difference between StartTime and EndTime as
* a doubleing point value indicating the elapsed time in seconds.
*/
double GetElapsedTime();
protected:
vtkTimerLog()
{
this->StartTime = 0;
this->EndTime = 0;
} // insure constructor/destructor protected
~vtkTimerLog() override {}
static int Logging;
static int Indent;
static int MaxEntries;
static int NextEntry;
static int WrapFlag;
static int TicksPerSecond;
static std::vector<vtkTimerLogEntry> TimerLog;
#ifdef _WIN32
#ifndef _WIN32_WCE
static timeb FirstWallTime;
static timeb CurrentWallTime;
#else
static FILETIME FirstWallTime;
static FILETIME CurrentWallTime;
#endif
#else
static timeval FirstWallTime;
static timeval CurrentWallTime;
static tms FirstCpuTicks;
static tms CurrentCpuTicks;
#endif
/**
* Record a timing event and capture wall time and cpu ticks.
*/
static void MarkEventInternal(const char* EventString, vtkTimerLogEntry::LogEntryType type,
vtkTimerLogEntry* entry = nullptr);
// instance variables to support simple timing functionality,
// separate from timer table logging.
double StartTime;
double EndTime;
static vtkTimerLogEntry* GetEvent(int i);
static void DumpEntry(ostream& os, int index, double time, double deltatime, int tick,
int deltatick, const char* event);
private:
vtkTimerLog(const vtkTimerLog&) = delete;
void operator=(const vtkTimerLog&) = delete;
};
/**
* Helper class to log time within scope
*/
class vtkTimerLogScope
{
public:
vtkTimerLogScope(const char* eventString)
{
if (eventString)
{
this->EventString = eventString;
}
vtkTimerLog::MarkStartEvent(eventString);
}
~vtkTimerLogScope() { vtkTimerLog::MarkEndEvent(this->EventString.c_str()); };
protected:
std::string EventString;
private:
vtkTimerLogScope(const vtkTimerLogScope&) = delete;
void operator=(const vtkTimerLogScope&) = delete;
};
//
// Set built-in type. Creates member Set"name"() (e.g., SetVisibility());
//
#define vtkTimerLogMacro(string) \
{ \
vtkTimerLog::FormatAndMarkEvent( \
"Mark: In %s, line %d, class %s: %s", __FILE__, __LINE__, this->GetClassName(), string); \
}
#endif