aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/utils/timer.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/utils/timer.h')
-rw-r--r--src/lib/utils/timer.h216
1 files changed, 216 insertions, 0 deletions
diff --git a/src/lib/utils/timer.h b/src/lib/utils/timer.h
new file mode 100644
index 000000000..6a6b807db
--- /dev/null
+++ b/src/lib/utils/timer.h
@@ -0,0 +1,216 @@
+/*
+* (C) 2018 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_TIMER_H_
+#define BOTAN_TIMER_H_
+
+#include <botan/types.h>
+#include <botan/internal/os_utils.h>
+#include <string>
+#include <chrono>
+
+namespace Botan {
+
+class BOTAN_TEST_API Timer final
+ {
+ public:
+ Timer(const std::string& name,
+ const std::string& provider,
+ const std::string& doing,
+ uint64_t event_mult,
+ size_t buf_size,
+ double clock_cycle_ratio,
+ uint64_t clock_speed)
+ : m_name(name + ((provider.empty() || provider == "base") ? "" : " [" + provider + "]"))
+ , m_doing(doing)
+ , m_buf_size(buf_size)
+ , m_event_mult(event_mult)
+ , m_clock_cycle_ratio(clock_cycle_ratio)
+ , m_clock_speed(clock_speed)
+ {}
+
+ Timer(const std::string& name, size_t buf_size = 0) :
+ Timer(name, "", "", 1, buf_size, 0.0, 0.0)
+ {}
+
+ Timer(const Timer& other) = default;
+
+ static uint64_t get_system_timestamp_ns()
+ {
+ return Botan::OS::get_system_timestamp_ns();
+ }
+
+ static uint64_t get_cpu_cycle_counter()
+ {
+ return Botan::OS::get_processor_timestamp();
+ }
+
+ void start()
+ {
+ stop();
+ m_timer_start = Timer::get_system_timestamp_ns();
+ m_cpu_cycles_start = Timer::get_cpu_cycle_counter();
+ }
+
+ void stop();
+
+ bool under(std::chrono::milliseconds msec)
+ {
+ return (milliseconds() < msec.count());
+ }
+
+ class Timer_Scope final
+ {
+ public:
+ explicit Timer_Scope(Timer& timer)
+ : m_timer(timer)
+ {
+ m_timer.start();
+ }
+ ~Timer_Scope()
+ {
+ try
+ {
+ m_timer.stop();
+ }
+ catch(...) {}
+ }
+ private:
+ Timer& m_timer;
+ };
+
+ template<typename F>
+ auto run(F f) -> decltype(f())
+ {
+ Timer_Scope timer(*this);
+ return f();
+ }
+
+ template<typename F>
+ void run_until_elapsed(std::chrono::milliseconds msec, F f)
+ {
+ while(this->under(msec))
+ {
+ run(f);
+ }
+ }
+
+ uint64_t value() const
+ {
+ return m_time_used;
+ }
+
+ double seconds() const
+ {
+ return milliseconds() / 1000.0;
+ }
+
+ double milliseconds() const
+ {
+ return value() / 1000000.0;
+ }
+
+ double ms_per_event() const
+ {
+ return milliseconds() / events();
+ }
+
+ uint64_t cycles_consumed() const
+ {
+ if(m_clock_speed != 0)
+ {
+ return (static_cast<double>(m_clock_speed) * value()) / 1000;
+ }
+ return m_cpu_cycles_used;
+ }
+
+ uint64_t events() const
+ {
+ return m_event_count * m_event_mult;
+ }
+
+ const std::string& get_name() const
+ {
+ return m_name;
+ }
+
+ const std::string& doing() const
+ {
+ return m_doing;
+ }
+
+ size_t buf_size() const
+ {
+ return m_buf_size;
+ }
+
+ double bytes_per_second() const
+ {
+ return seconds() > 0.0 ? events() / seconds() : 0.0;
+ }
+
+ double events_per_second() const
+ {
+ return seconds() > 0.0 ? events() / seconds() : 0.0;
+ }
+
+ double seconds_per_event() const
+ {
+ return events() > 0 ? seconds() / events() : 0.0;
+ }
+
+ void set_custom_msg(const std::string& s)
+ {
+ m_custom_msg = s;
+ }
+
+ bool operator<(const Timer& other) const
+ {
+ if(this->doing() != other.doing())
+ return (this->doing() < other.doing());
+
+ return (this->get_name() < other.get_name());
+ }
+
+ std::string to_string() const
+ {
+ if(m_custom_msg.size() > 0)
+ {
+ return m_custom_msg;
+ }
+ else if(this->buf_size() == 0)
+ {
+ return result_string_ops();
+ }
+ else
+ {
+ return result_string_bps();
+ }
+ }
+
+ private:
+ std::string result_string_bps() const;
+ std::string result_string_ops() const;
+
+ // const data
+ std::string m_name, m_doing;
+ size_t m_buf_size;
+ uint64_t m_event_mult;
+ double m_clock_cycle_ratio;
+ uint64_t m_clock_speed;
+
+ // set at runtime
+ std::string m_custom_msg;
+ uint64_t m_time_used = 0, m_timer_start = 0;
+ uint64_t m_event_count = 0;
+
+ uint64_t m_max_time = 0, m_min_time = 0;
+ uint64_t m_cpu_cycles_start = 0, m_cpu_cycles_used = 0;
+ };
+
+}
+
+#endif