Program Listing for File Timing.h
↰ Return to documentation for file (Utilities/Timing.h)
#ifndef __Timing_H__
#define __Timing_H__
#include <iostream>
#include <stack>
#include <unordered_map>
#include "Logger.h"
#include <chrono>
namespace Utilities
{
#define START_TIMING(timerName) \
Utilities::Timing::startTiming(timerName);
#define STOP_TIMING \
Utilities::Timing::stopTiming(false);
#define STOP_TIMING_PRINT \
Utilities::Timing::stopTiming(true);
#define STOP_TIMING_AVG \
{ \
static int timing_timerId = -1; \
Utilities::Timing::stopTiming(false, timing_timerId); \
}
#define STOP_TIMING_AVG_PRINT \
{ \
static int timing_timerId = -1; \
Utilities::Timing::stopTiming(true, timing_timerId); \
}
#define INIT_TIMING \
int Utilities::IDFactory::id = 0; \
std::unordered_map<int, Utilities::AverageTime> Utilities::Timing::m_averageTimes; \
std::stack<Utilities::TimingHelper> Utilities::Timing::m_timingStack; \
bool Utilities::Timing::m_dontPrintTimes = false; \
unsigned int Utilities::Timing::m_startCounter = 0; \
unsigned int Utilities::Timing::m_stopCounter = 0;
struct TimingHelper
{
std::chrono::time_point<std::chrono::high_resolution_clock> start;
std::string name;
};
struct AverageTime
{
double totalTime;
unsigned int counter;
std::string name;
};
class IDFactory
{
private:
static int id;
public:
static int getId() { return id++; }
};
class Timing
{
public:
static bool m_dontPrintTimes;
static unsigned int m_startCounter;
static unsigned int m_stopCounter;
static std::stack<TimingHelper> m_timingStack;
static std::unordered_map<int, AverageTime> m_averageTimes;
static void reset()
{
while (!m_timingStack.empty())
m_timingStack.pop();
m_averageTimes.clear();
m_startCounter = 0;
m_stopCounter = 0;
}
FORCE_INLINE static void startTiming(const std::string& name = std::string(""))
{
TimingHelper h;
h.start = std::chrono::high_resolution_clock::now();
h.name = name;
Timing::m_timingStack.push(h);
Timing::m_startCounter++;
}
FORCE_INLINE static double stopTiming(bool print = true)
{
if (!Timing::m_timingStack.empty())
{
Timing::m_stopCounter++;
std::chrono::time_point<std::chrono::high_resolution_clock> stop = std::chrono::high_resolution_clock::now();
TimingHelper h = Timing::m_timingStack.top();
Timing::m_timingStack.pop();
std::chrono::duration<double> elapsed_seconds = stop - h.start;
double t = elapsed_seconds.count() * 1000.0;
if (print)
LOG_INFO << "time " << h.name.c_str() << ": " << t << " ms";
return t;
}
return 0;
}
FORCE_INLINE static double stopTiming(bool print, int &id)
{
if (id == -1)
id = IDFactory::getId();
if (!Timing::m_timingStack.empty())
{
Timing::m_stopCounter++;
std::chrono::time_point<std::chrono::high_resolution_clock> stop = std::chrono::high_resolution_clock::now();
TimingHelper h = Timing::m_timingStack.top();
Timing::m_timingStack.pop();
std::chrono::duration<double> elapsed_seconds = stop - h.start;
double t = elapsed_seconds.count() * 1000.0;
if (print && !Timing::m_dontPrintTimes)
LOG_INFO << "time " << h.name.c_str() << ": " << t << " ms";
if (id >= 0)
{
std::unordered_map<int, AverageTime>::iterator iter;
iter = Timing::m_averageTimes.find(id);
if (iter != Timing::m_averageTimes.end())
{
Timing::m_averageTimes[id].totalTime += t;
Timing::m_averageTimes[id].counter++;
}
else
{
AverageTime at;
at.counter = 1;
at.totalTime = t;
at.name = h.name;
Timing::m_averageTimes[id] = at;
}
}
return t;
}
return 0;
}
FORCE_INLINE static void printAverageTimes()
{
std::unordered_map<int, AverageTime>::iterator iter;
for (iter = Timing::m_averageTimes.begin(); iter != Timing::m_averageTimes.end(); iter++)
{
AverageTime &at = iter->second;
const double avgTime = at.totalTime / at.counter;
LOG_INFO << "Average time: " << at.name.c_str() << ": " << avgTime << " ms";
}
if (Timing::m_startCounter != Timing::m_stopCounter)
LOG_INFO << "Problem: " << Timing::m_startCounter << " calls of startTiming and " << Timing::m_stopCounter << " calls of stopTiming. ";
LOG_INFO << "---------------------------------------------------------------------------\n";
}
FORCE_INLINE static void printTimeSums()
{
std::unordered_map<int, AverageTime>::iterator iter;
for (iter = Timing::m_averageTimes.begin(); iter != Timing::m_averageTimes.end(); iter++)
{
AverageTime &at = iter->second;
const double timeSum = at.totalTime;
LOG_INFO << "Time sum: " << at.name.c_str() << ": " << timeSum << " ms";
}
if (Timing::m_startCounter != Timing::m_stopCounter)
LOG_INFO << "Problem: " << Timing::m_startCounter << " calls of startTiming and " << Timing::m_stopCounter << " calls of stopTiming. ";
LOG_INFO << "---------------------------------------------------------------------------\n";
}
};
}
#endif