From fa0e462444312d0f7e59c08f888b82fd83be95a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me?= Date: Wed, 24 Apr 2019 12:13:56 +0200 Subject: [PATCH] Added a basic timer in utils.hpp. --- utils.hpp | 71 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 9 deletions(-) diff --git a/utils.hpp b/utils.hpp index 376a6b4..8ceccf7 100644 --- a/utils.hpp +++ b/utils.hpp @@ -17,23 +17,76 @@ template auto max(const T & a, const T2 & b) -> decltyp /// To be sure that floating point numbers won't be casted to integers in ::abs()... template T sureAbs(const T & x) { return (x < T(0)) ? -x : x; } + +//* +/// Generic operator<< for ostream, (to print std::vector, etd::list, std::map, etc). Can generate conflicts with specialized operator<< overloads. template class C, class... Args> std::ostream& operator<<(std::ostream& os, const C& objs) { for (auto const& obj : objs) os << obj << ' '; return os; -} +}//*/ -/// Convenience template class to do StdPairValueCatcher(a, b) = someFunctionThatReturnsAnStdPair() -/// Instead of doing a = std::get<0>(result_from_function), b = std::get<1>(result_from_function) -template -struct StdPairValueCatcher +/// define UTILS_NO_CHRONO to deactivate chronometer +#ifndef UTILS_NO_CHRONO + +#include +#include +#include +#include + +/// Convenience macro to create a Chronometer object that will measure the execution time of its scope. +#define TIMER(str) Chronometer __chrono((str)) + +/// \class Chronometer class. Used to measure the execution time of its scope. +/// +/// Usage : +/// +/// { +/// TIMER("My timer"); +/// /* some code to be profiled */ +/// }// <--- the chronometer measures the time between the call to its constructor and the call to its destructor. +/// +/// Possible output : +/// +/// My timer : 0.12317568 s (+/- 1e-09 s) +/// +template +struct Chronometer { - A & a; - B & b; - StdPairValueCatcher(A & a_, B & b_) : a(a_), b(b_) {} - std::pair const& operator=(std::pair const& p) {a = std::get<0>(p); b = std::get<1>(p); return p; } + std::string name; + std::chrono::high_resolution_clock::time_point t0; + + /// Creates the Chronometer object with the provided name and stores the time. + Chronometer(const std::string & name_ = "") + : name(name_), + t0(std::chrono::high_resolution_clock::now()) + {} + + /// Measures the time elapsed between the creation of the object and its destruction, and prints the result in std::cout. + ~Chronometer() { MeasureTimeElapsed(); } + + /// Resets the timer. Allows the measurement of the execution time of several sub-intervals in the current scope. + void Reset() { t0 = std::chrono::high_resolution_clock::now(); } + + /// Measures the time elapsed between the creation of the object and its destruction, and prints the result in std::cout. + void MeasureTimeElapsed() + { + // measure time since object creation + std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); + std::chrono::duration time_span = std::chrono::duration_cast>(t1 - t0); + // clock resolution + auto resolution_ratio = std::chrono::high_resolution_clock::period(); + double resolution = double(resolution_ratio.num)/resolution_ratio.den; + + std::cout.precision(16); + std::cout << name.c_str() << "\t: " << time_span.count() << " s (+/- " << resolution << " s)" << std::endl;// use of c_str() so that there is no ambiguity with the generic operator<< + } }; +#else// chronometer + #define TIMER(str) +#endif// chronometer + #endif