File indexing completed on 2024-11-16 09:01:24
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009
0010
0011 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5 && __GNUC_MINOR__ < 8
0012 #define _GLIBCXX_USE_NANOSLEEP
0013 #endif
0014
0015 #include <array>
0016 #include <chrono>
0017 #include <functional>
0018 #include <iostream>
0019 #include <string>
0020 #include <utility>
0021
0022 namespace CLI {
0023
0024
0025 class Timer {
0026 protected:
0027
0028 using clock = std::chrono::steady_clock;
0029
0030
0031 using time_point = std::chrono::time_point<clock>;
0032
0033
0034 using time_print_t = std::function<std::string(std::string, std::string)>;
0035
0036
0037 std::string title_;
0038
0039
0040 time_print_t time_print_;
0041
0042
0043 time_point start_;
0044
0045
0046 std::size_t cycles{1};
0047
0048 public:
0049
0050 static std::string Simple(std::string title, std::string time) { return title + ": " + time; }
0051
0052
0053 static std::string Big(std::string title, std::string time) {
0054 return std::string("-----------------------------------------\n") + "| " + title + " | Time = " + time + "\n" +
0055 "-----------------------------------------";
0056 }
0057
0058 public:
0059
0060 explicit Timer(std::string title = "Timer", time_print_t time_print = Simple)
0061 : title_(std::move(title)), time_print_(std::move(time_print)), start_(clock::now()) {}
0062
0063
0064 std::string time_it(std::function<void()> f, double target_time = 1) {
0065 time_point start = start_;
0066 double total_time;
0067
0068 start_ = clock::now();
0069 std::size_t n = 0;
0070 do {
0071 f();
0072 std::chrono::duration<double> elapsed = clock::now() - start_;
0073 total_time = elapsed.count();
0074 } while(n++ < 100u && total_time < target_time);
0075
0076 std::string out = make_time_str(total_time / static_cast<double>(n)) + " for " + std::to_string(n) + " tries";
0077 start_ = start;
0078 return out;
0079 }
0080
0081
0082 std::string make_time_str() const {
0083 time_point stop = clock::now();
0084 std::chrono::duration<double> elapsed = stop - start_;
0085 double time = elapsed.count() / static_cast<double>(cycles);
0086 return make_time_str(time);
0087 }
0088
0089
0090
0091 std::string make_time_str(double time) const {
0092 auto print_it = [](double x, std::string unit) {
0093 const unsigned int buffer_length = 50;
0094 std::array<char, buffer_length> buffer;
0095 std::snprintf(buffer.data(), buffer_length, "%.5g", x);
0096 return buffer.data() + std::string(" ") + unit;
0097 };
0098
0099 if(time < .000001)
0100 return print_it(time * 1000000000, "ns");
0101 else if(time < .001)
0102 return print_it(time * 1000000, "us");
0103 else if(time < 1)
0104 return print_it(time * 1000, "ms");
0105 else
0106 return print_it(time, "s");
0107 }
0108
0109
0110
0111 std::string to_string() const { return time_print_(title_, make_time_str()); }
0112
0113
0114 Timer &operator/(std::size_t val) {
0115 cycles = val;
0116 return *this;
0117 }
0118 };
0119
0120
0121 class AutoTimer : public Timer {
0122 public:
0123
0124 explicit AutoTimer(std::string title = "Timer", time_print_t time_print = Simple) : Timer(title, time_print) {}
0125
0126
0127
0128 ~AutoTimer() { std::cout << to_string() << std::endl; }
0129 };
0130
0131 }
0132
0133
0134 inline std::ostream &operator<<(std::ostream &in, const CLI::Timer &timer) { return in << timer.to_string(); }