diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 17:44:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 17:44:55 +0000 |
commit | 5068d34c08f951a7ea6257d305a1627b09a95817 (patch) | |
tree | 08213e2be853396a3b07ce15dbe222644dcd9a89 /src/third-party/CLI/Timer.hpp | |
parent | Initial commit. (diff) | |
download | lnav-5068d34c08f951a7ea6257d305a1627b09a95817.tar.xz lnav-5068d34c08f951a7ea6257d305a1627b09a95817.zip |
Adding upstream version 0.11.1.upstream/0.11.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/third-party/CLI/Timer.hpp')
-rw-r--r-- | src/third-party/CLI/Timer.hpp | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/third-party/CLI/Timer.hpp b/src/third-party/CLI/Timer.hpp new file mode 100644 index 0000000..e97b17c --- /dev/null +++ b/src/third-party/CLI/Timer.hpp @@ -0,0 +1,134 @@ +// Copyright (c) 2017-2022, University of Cincinnati, developed by Henry Schreiner +// under NSF AWARD 1414736 and by the respective contributors. +// All rights reserved. +// +// SPDX-License-Identifier: BSD-3-Clause + +#pragma once + +// On GCC < 4.8, the following define is often missing. Due to the +// fact that this library only uses sleep_for, this should be safe +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5 && __GNUC_MINOR__ < 8 +#define _GLIBCXX_USE_NANOSLEEP +#endif + +#include <array> +#include <chrono> +#include <functional> +#include <iostream> +#include <string> +#include <utility> + +namespace CLI { + +/// This is a simple timer with pretty printing. Creating the timer starts counting. +class Timer { + protected: + /// This is a typedef to make clocks easier to use + using clock = std::chrono::steady_clock; + + /// This typedef is for points in time + using time_point = std::chrono::time_point<clock>; + + /// This is the type of a printing function, you can make your own + using time_print_t = std::function<std::string(std::string, std::string)>; + + /// This is the title of the timer + std::string title_; + + /// This is the function that is used to format most of the timing message + time_print_t time_print_; + + /// This is the starting point (when the timer was created) + time_point start_; + + /// This is the number of times cycles (print divides by this number) + std::size_t cycles{1}; + + public: + /// Standard print function, this one is set by default + static std::string Simple(std::string title, std::string time) { return title + ": " + time; } + + /// This is a fancy print function with --- headers + static std::string Big(std::string title, std::string time) { + return std::string("-----------------------------------------\n") + "| " + title + " | Time = " + time + "\n" + + "-----------------------------------------"; + } + + public: + /// Standard constructor, can set title and print function + explicit Timer(std::string title = "Timer", time_print_t time_print = Simple) + : title_(std::move(title)), time_print_(std::move(time_print)), start_(clock::now()) {} + + /// Time a function by running it multiple times. Target time is the len to target. + std::string time_it(std::function<void()> f, double target_time = 1) { + time_point start = start_; + double total_time; + + start_ = clock::now(); + std::size_t n = 0; + do { + f(); + std::chrono::duration<double> elapsed = clock::now() - start_; + total_time = elapsed.count(); + } while(n++ < 100u && total_time < target_time); + + std::string out = make_time_str(total_time / static_cast<double>(n)) + " for " + std::to_string(n) + " tries"; + start_ = start; + return out; + } + + /// This formats the numerical value for the time string + std::string make_time_str() const { + time_point stop = clock::now(); + std::chrono::duration<double> elapsed = stop - start_; + double time = elapsed.count() / static_cast<double>(cycles); + return make_time_str(time); + } + + // LCOV_EXCL_START + /// This prints out a time string from a time + std::string make_time_str(double time) const { + auto print_it = [](double x, std::string unit) { + const unsigned int buffer_length = 50; + std::array<char, buffer_length> buffer; + std::snprintf(buffer.data(), buffer_length, "%.5g", x); + return buffer.data() + std::string(" ") + unit; + }; + + if(time < .000001) + return print_it(time * 1000000000, "ns"); + else if(time < .001) + return print_it(time * 1000000, "us"); + else if(time < 1) + return print_it(time * 1000, "ms"); + else + return print_it(time, "s"); + } + // LCOV_EXCL_STOP + + /// This is the main function, it creates a string + std::string to_string() const { return time_print_(title_, make_time_str()); } + + /// Division sets the number of cycles to divide by (no graphical change) + Timer &operator/(std::size_t val) { + cycles = val; + return *this; + } +}; + +/// This class prints out the time upon destruction +class AutoTimer : public Timer { + public: + /// Reimplementing the constructor is required in GCC 4.7 + explicit AutoTimer(std::string title = "Timer", time_print_t time_print = Simple) : Timer(title, time_print) {} + // GCC 4.7 does not support using inheriting constructors. + + /// This destructor prints the string + ~AutoTimer() { std::cout << to_string() << std::endl; } +}; + +} // namespace CLI + +/// This prints out the time if shifted into a std::cout like stream. +inline std::ostream &operator<<(std::ostream &in, const CLI::Timer &timer) { return in << timer.to_string(); } |