diff --git a/include/ircd/util/timer.h b/include/ircd/util/timer.h index 1face1f48..769a9fcb4 100644 --- a/include/ircd/util/timer.h +++ b/include/ircd/util/timer.h @@ -17,19 +17,46 @@ inline namespace util struct timer; }} +/// Stopwatch w/ accumulation. +/// +/// This utility can be used to gauge the duration of something. The clock +/// is started by default upon construction. Users can query the running time +/// using the at(), or using the pretty() convenience. +/// +/// This timer features an accumulator state so the clock can be stopped and +/// continued, and each time the accumulator is updated. The accumulator +/// value is always added into results: when the timer is stopped, the result +/// is simply the accumulator value; when the clock is running, the result is +/// the accumulator value added to the difference of the current time and the +/// last start time. +/// +/// One can instantiate the timer without starting the clock with the `nostart` +/// overload. Additionally, a lambda constructor will accumulate the time it +/// takes to execute the provided function. struct ircd::util::timer { - IRCD_OVERLOAD(nostart) using clock = std::chrono::steady_clock; + IRCD_OVERLOAD(nostart) - nanoseconds accumulator {0ns}; - clock::time_point start {clock::now()}; + nanoseconds accumulator + { + 0ns + }; + clock::time_point start + { + clock::now() + }; + + // Observers bool stopped() const; - template duration get() const; template duration at() const; + + // Convenience wrapper for util::pretty() string_view pretty(const mutable_buffer &out, const int &fmt = 0) const; std::string pretty(const int &fmt = 0) const; + + // Control void cont(); void stop(); @@ -40,23 +67,40 @@ struct ircd::util::timer inline ircd::util::timer::timer(nostart_t) -:start{clock::time_point::min()} +:start { + clock::time_point::min() } +{} template -duration +inline duration ircd::util::timer::at() const { - const auto now(clock::now()); - return duration_cast(now - start); + const auto now + { + !stopped()? + clock::now(): + start + }; + + const auto elapsed + { + duration_cast(now - start) + }; + + const auto accumulator + { + this->accumulator + elapsed + }; + + return duration_cast(accumulator); } -template -duration -ircd::util::timer::get() +inline bool +ircd::util::timer::stopped() const { - return std::chrono::duration_cast(accumulator); + return start == clock::time_point::min(); } diff --git a/ircd/util.cc b/ircd/util.cc index 80eb86a69..1da9ca25c 100644 --- a/ircd/util.cc +++ b/ircd/util.cc @@ -283,31 +283,46 @@ ircd::util::timer::timer(const std::function &func) void ircd::util::timer::stop() { - if(stopped()) - return; + const auto now + { + !stopped()? + clock::now(): + start + }; - const auto now(clock::now()); - accumulator += std::chrono::duration_cast(now - start); + const auto elapsed + { + duration_cast(now - start) + }; + + accumulator += elapsed; start = clock::time_point::min(); } void ircd::util::timer::cont() { - if(!stopped()) + const auto now { - const auto now(clock::now()); - accumulator += std::chrono::duration_cast(now - start); - } + clock::now() + }; - start = clock::now(); + const auto elapsed + { + !stopped()? + duration_cast(now - start): + decltype(accumulator)(0) + }; + + accumulator += elapsed; + start = now; } std::string ircd::util::timer::pretty(const int &fmt) const { - return util::pretty(at(), fmt); + return util::pretty(at(), fmt); } ircd::string_view @@ -315,14 +330,7 @@ ircd::util::timer::pretty(const mutable_buffer &out, const int &fmt) const { - return util::pretty(out, at(), fmt); -} - -bool -ircd::util::timer::stopped() -const -{ - return start == clock::time_point::min(); + return util::pretty(out, at(), fmt); } ///////////////////////////////////////////////////////////////////////////////