#ifndef __JEEP__JTIMER__ #define __JEEP__JTIMER__ #include #include #include #include #include #include #include "JLang/JTitle.hh" #include "Jeep/JPrint.hh" #include "Jeep/JScale.hh" /** * \author mdejong */ namespace JEEP {} namespace JPP { using namespace JEEP; } namespace JEEP { using JLANG::JTitle; /** * Auxiliary class for CPU timing and usage. */ class JTimer : public JTitle { public: typedef unsigned long long ull; /** * Status of clock. */ enum JStatus_t { CLK_STOPPED = 0, CLK_RUNNING = 1 }; /** * Default constructor. */ JTimer() : JTitle(), usec_wall(0ULL), usec_ucpu(0ULL), usec_scpu(0ULL), counter (0ULL), status (CLK_STOPPED) {} /** * Constructor. * * \param title title */ JTimer(const JTitle& title) : JTitle(title), usec_wall(0ULL), usec_ucpu(0ULL), usec_scpu(0ULL), counter (0ULL), status (CLK_STOPPED) {} /** * Reset timer. */ void reset() { usec_wall = 0; usec_ucpu = 0; usec_scpu = 0; counter = 0; status = CLK_STOPPED; } /** * Start timer. */ void start() { if (status == CLK_STOPPED) { struct timeval tv; struct rusage usage; gettimeofday(&tv, NULL); getrusage(RUSAGE_SELF, &usage); usec_wall -= timeval_to_usec(tv); usec_ucpu -= timeval_to_usec(usage.ru_utime); usec_scpu -= timeval_to_usec(usage.ru_stime); status = CLK_RUNNING; ++counter; } } /** * Stop timer. */ void stop() { if (status == CLK_RUNNING) { struct timeval tv; struct rusage usage; gettimeofday(&tv, NULL); getrusage(RUSAGE_SELF, &usage); usec_wall += timeval_to_usec(tv); usec_ucpu += timeval_to_usec(usage.ru_utime); usec_scpu += timeval_to_usec(usage.ru_stime); } status = CLK_STOPPED; } /** * Get CPU usage. * * \return CPU usage [%] */ unsigned int timing_get_cpu_percentage() const { return (100ULL * (usec_ucpu + usec_scpu) / (usec_wall+1)); } /** * Convert timeval to micro-seconds. * * \param tv timeval * \return time [us] */ static inline unsigned long long timeval_to_usec(const struct timeval& tv) { return (unsigned long long) tv.tv_sec * 1000000ULL + (unsigned long long) tv.tv_usec; } /** * Print timer data. * * \param out output stream * \param scale scale */ void print(std::ostream& out, const JScale_t scale = milli_t) const { print(out, 1.0, scale); } /** * Print timer data. * * \param out output stream * \param normalise normalise to number of starts * \param scale scale */ void print(std::ostream& out, const bool normalise, const JScale_t scale = milli_t) const { double factor = 1.0; if (normalise && counter != 0) { factor = 1.0 / (double) counter; } print(out, factor, scale); } /** * Print timer data. * * \param out output stream * \param factor multiplication factor * \param scale scale */ void print(std::ostream& out, const double factor, const JScale_t scale = milli_t) const { using namespace std; const double y = factor * 1e-3 * getValue(milli_t) / getValue(scale); const char* u = getUnit(scale); out << getTitle() << endl; out << FIXED(10,3) << usec_wall * y << " " << u << "s elapsed" << endl; out << FIXED(10,3) << usec_ucpu * y << " " << u << "s user" << endl; out << FIXED(10,3) << usec_scpu * y << " " << u << "s system" << endl; out << setw( 3) << timing_get_cpu_percentage() << "%CPU" << endl; } /** * Print timer data. * * \param out output stream * \param timer timer * \return output stream */ friend inline std::ostream& operator<<(std::ostream& out, const JTimer& timer) { timer.print(out); return out; } public: unsigned long long usec_wall; /* clock time */ unsigned long long usec_ucpu; /* CPU user time */ unsigned long long usec_scpu; /* CPU system time */ unsigned long long counter; /* counter */ protected: JStatus_t status; }; } #endif