diff options
author | Tor Brede Vekterli <vekterli@yahoo-inc.com> | 2016-11-28 15:08:43 +0100 |
---|---|---|
committer | Tor Brede Vekterli <vekterli@yahoo-inc.com> | 2016-11-28 15:11:55 +0100 |
commit | c81a8988422515e4ae642d832c4eeeddac764fc2 (patch) | |
tree | 0d3fdf90b569185cace905c21f7c911c7320e672 /storageframework | |
parent | e548190672bc4d23990507a81c336ed151753c13 (diff) |
Add monotonic clock support to storage framework
Let MilliSecTimer expose elapsed time as a double instead of quantizing
down elapsed time to discrete millliseconds.
Remove really gnarly implicit time_t operator conversion in favor of
an explicit duration reporting method.
Diffstat (limited to 'storageframework')
6 files changed, 51 insertions, 30 deletions
diff --git a/storageframework/src/vespa/storageframework/defaultimplementation/clock/fakeclock.h b/storageframework/src/vespa/storageframework/defaultimplementation/clock/fakeclock.h index f15414b3f51..c4659bea21e 100644 --- a/storageframework/src/vespa/storageframework/defaultimplementation/clock/fakeclock.h +++ b/storageframework/src/vespa/storageframework/defaultimplementation/clock/fakeclock.h @@ -19,7 +19,7 @@ struct FakeClock : public framework::Clock { enum Mode { FAKE_ABSOLUTE, // Time is always equal to supplied absolute time FAKE_ABSOLUTE_CYCLE // Time is equal to absolute time + counter that - // increase for each request so you never get same + // increases for each request so you never get same // timestamp twice. }; @@ -63,17 +63,22 @@ public: _absoluteTime += framework::MicroSecTime(nr * uint64_t(1000000)); } - virtual framework::MicroSecTime getTimeInMicros() const { + framework::MicroSecTime getTimeInMicros() const override { vespalib::LockGuard guard(_lock); if (_mode == FAKE_ABSOLUTE) return _absoluteTime; return _absoluteTime + framework::MicroSecTime(1000000 * _cycleCount++); } - virtual framework::MilliSecTime getTimeInMillis() const { + framework::MilliSecTime getTimeInMillis() const override { return getTimeInMicros().getMillis(); } - virtual framework::SecondTime getTimeInSeconds() const { + framework::SecondTime getTimeInSeconds() const override { return getTimeInMicros().getSeconds(); } + framework::MonotonicTimePoint getMonotonicTime() const override { + // For simplicity, assume fake monotonic time follows fake wall clock. + return MonotonicTimePoint(std::chrono::microseconds( + getTimeInMicros().getTime())); + } }; } // defaultimplementation diff --git a/storageframework/src/vespa/storageframework/defaultimplementation/clock/realclock.cpp b/storageframework/src/vespa/storageframework/defaultimplementation/clock/realclock.cpp index e9348512427..86343a7c4ea 100644 --- a/storageframework/src/vespa/storageframework/defaultimplementation/clock/realclock.cpp +++ b/storageframework/src/vespa/storageframework/defaultimplementation/clock/realclock.cpp @@ -9,31 +9,29 @@ namespace storage { namespace framework { namespace defaultimplementation { -MicroSecTime -RealClock::getTimeInMicros() const -{ +MicroSecTime RealClock::getTimeInMicros() const { struct timeval mytime; gettimeofday(&mytime, 0); return MicroSecTime(mytime.tv_sec * 1000000llu + mytime.tv_usec); } -MilliSecTime -RealClock::getTimeInMillis() const -{ +MilliSecTime RealClock::getTimeInMillis() const { struct timeval mytime; gettimeofday(&mytime, 0); return MilliSecTime( mytime.tv_sec * 1000llu + mytime.tv_usec / 1000); } -SecondTime -RealClock::getTimeInSeconds() const -{ +SecondTime RealClock::getTimeInSeconds() const { struct timeval mytime; gettimeofday(&mytime, 0); return SecondTime(mytime.tv_sec); } +MonotonicTimePoint RealClock::getMonotonicTime() const { + return std::chrono::steady_clock::now(); +} + } // defaultimplementation } // framework } // storage diff --git a/storageframework/src/vespa/storageframework/defaultimplementation/clock/realclock.h b/storageframework/src/vespa/storageframework/defaultimplementation/clock/realclock.h index 633ab126c45..a8fd5d597d7 100644 --- a/storageframework/src/vespa/storageframework/defaultimplementation/clock/realclock.h +++ b/storageframework/src/vespa/storageframework/defaultimplementation/clock/realclock.h @@ -16,9 +16,10 @@ namespace framework { namespace defaultimplementation { struct RealClock : public Clock { - virtual MicroSecTime getTimeInMicros() const; - virtual MilliSecTime getTimeInMillis() const; - virtual SecondTime getTimeInSeconds() const; + MicroSecTime getTimeInMicros() const override; + MilliSecTime getTimeInMillis() const override; + SecondTime getTimeInSeconds() const override; + MonotonicTimePoint getMonotonicTime() const override; }; } // defaultimplementation diff --git a/storageframework/src/vespa/storageframework/generic/clock/clock.h b/storageframework/src/vespa/storageframework/generic/clock/clock.h index bd9415a5a8c..acc7a537418 100644 --- a/storageframework/src/vespa/storageframework/generic/clock/clock.h +++ b/storageframework/src/vespa/storageframework/generic/clock/clock.h @@ -13,20 +13,24 @@ #pragma once -#include <memory> #include <vespa/storageframework/generic/clock/time.h> +#include <memory> +#include <chrono> namespace storage { namespace framework { struct Clock { - typedef std::unique_ptr<Clock> UP; + using UP = std::unique_ptr<Clock>; virtual ~Clock() {} virtual MicroSecTime getTimeInMicros() const = 0; virtual MilliSecTime getTimeInMillis() const = 0; virtual SecondTime getTimeInSeconds() const = 0; + + // Time point resolution is intentionally not defined here. + virtual MonotonicTimePoint getMonotonicTime() const = 0; }; } // framework diff --git a/storageframework/src/vespa/storageframework/generic/clock/time.h b/storageframework/src/vespa/storageframework/generic/clock/time.h index e09a4d5ef92..6e4ee615441 100644 --- a/storageframework/src/vespa/storageframework/generic/clock/time.h +++ b/storageframework/src/vespa/storageframework/generic/clock/time.h @@ -2,13 +2,17 @@ #pragma once #include <boost/operators.hpp> -#include <limits> #include <vespa/vespalib/stllike/string.h> #include <vespa/vespalib/stllike/asciistream.h> +#include <limits> +#include <chrono> namespace storage { namespace framework { +using MonotonicTimePoint = std::chrono::steady_clock::time_point; +using MonotonicDuration = std::chrono::steady_clock::duration; + class Clock; enum TimeFormat { @@ -27,6 +31,9 @@ enum TimeFormat { */ vespalib::string getTimeString(uint64_t microSecondTime, TimeFormat format); +// TODO deprecate framework time point and duration classes in favor of +// using std::chrono. + // As this class can't include clock, this utility function can be used in // header implementation to get actual time. uint64_t getRawMicroTime(const Clock&); diff --git a/storageframework/src/vespa/storageframework/generic/clock/timer.h b/storageframework/src/vespa/storageframework/generic/clock/timer.h index 66ff8cdef15..ea4568fc817 100644 --- a/storageframework/src/vespa/storageframework/generic/clock/timer.h +++ b/storageframework/src/vespa/storageframework/generic/clock/timer.h @@ -4,9 +4,6 @@ * \ingroup clock * * \brief Class used to measure time differences. - * - * This timer class is a simple class that then used as a time_t instance, it - * will calculate time difference from some preset point of time. */ #pragma once @@ -18,17 +15,26 @@ namespace framework { class MilliSecTimer { const Clock* _clock; - time_t _startTime; + MonotonicTimePoint _startTime; public: MilliSecTimer(const Clock& clock) - : _clock(&clock), _startTime(getCurrentTime()) {} - - MilliSecTime getTime() const { return MilliSecTime(getCurrentTime() - _startTime); } - operator time_t() const { return getCurrentTime() - _startTime; } - - time_t getCurrentTime() const - { return _clock->getTimeInMillis().getTime(); } + : _clock(&clock), _startTime(_clock->getMonotonicTime()) {} + + // Copy construction makes the most sense when creating a timer that is + // intended to inherit another timer's start time point, without incurring + // the cost of an initial clock sampling. + MilliSecTimer(const MilliSecTimer&) = default; + MilliSecTimer& operator=(const MilliSecTimer&) = default; + + MonotonicDuration getElapsedTime() const { + return _clock->getMonotonicTime() - _startTime; + } + + double getElapsedTimeAsDouble() const { + using ToDuration = std::chrono::duration<double, std::milli>; + return std::chrono::duration_cast<ToDuration>(getElapsedTime()).count(); + } }; } // framework |