// // Helper to benchmark time taken by functions // // Code taken from https://github.com/picanumber/bureaucrat/blob/master/time_lapse.h // and https://github.com/espressif/esp-dsp/blob/master/test/report.inc // #ifndef REPORT_HPP #define REPORT_HPP #include #include #include #include #include #include #include #include #define BENCHMARK(fct, ...) Report::benchmark(fct, __VA_ARGS__) using functionSignature = std::function; using imagesList = std::vector >; #define fw(what) std::forward(what) // ============== // class TestCase // ============== class TestCase { public: static constexpr int DEFAULT_ITERATIONS = 3; std::string name; std::vector resultTime; int iterations; functionSignature func; TestCase(std::string _name, int _iterations, functionSignature _func); TestCase(std::string _name, functionSignature _func); void executeOn(const imagesList &testImages); }; // =============== // class TestGroup // =============== class TestGroup { public: std::string name; std::vector tests; explicit TestGroup(std::string _name); void addTestCase(const TestCase& test); }; // ============= // class Summary // ============= class Summary { private: const int COL1_WIDTH = 50; const int COL_VALUES_WIDTH = 15; imagesList images; std::vector columnsWidth; int totalWidth; std::string lineSeparator(const char sep); std::string alignTextLeft(const std::string &text, int colWidth); std::string alignTextRight(const std::string &text, int colWidth); std::string alignTextCenter(const std::string &text, int colWidth); std::string lineText(const std::vector& colTexts); public: Summary(imagesList _images); std::string summaryHeader(const std::string &reportName); std::string summarySection(const TestGroup& group); std::string summaryTest(const TestCase& test); }; // ============ // class Report // ============ class Report /** * @ class report * @ brief Class to report a benchmark of image processing functions */ { private: std::string name; std::vector groups; imagesList images; Summary summary; public: explicit Report(std::string _name, const imagesList& _images); TestGroup& addGroup(const std::string &_name); TestGroup& getGroup(const std::string &_name); void startBenchmark(); std::string getSummary(); /** * Function that executes the function 'repeat' times, benchmark the average time taken and logs on the console * the time. * @tparam F * @tparam Args * @param unit String representing the time unit (for the log). Can be either 's', 'ms', 'us' or 'ns' * @param repeat Number of times to do the benchmark * @param func Function to benchmark * @param args Arguments of the function 'func' */ template static int64_t benchmark(int repeat, F&& func, Args&&... args) { auto avg = duration(func, (args)...); for(int i = 0; i < repeat-1; i++) { avg += duration(func, (args)...); } return (avg/repeat).count(); } template static int64_t benchmark(F&& func, Args&&... args) { const int defaultIterations = 3; return benchmark(defaultIterations, func, (args)...); } using TimeT = std::chrono::microseconds ; using ClockT = std::chrono::system_clock ; /** * @ fn duration * @ brief Returns the duration (in chrono's type system microseconds) of the elapsed time */ template static TimeT duration(F&& func, Args&&... args) { auto start = ClockT::now(); fw(func)(std::forward(args)...); return std::chrono::duration_cast(ClockT::now() - start); } }; #undef fw #endif // REPORT_HPP