Commit 479918de by Shahbaz Youssefi Committed by Commit Bot

Get absolute time from timers

Independent of start()/stop()/getElapsedTime() functionality, getAbsoluteTime() is added to return the time regardless of whether the timer is running. Bug: angleproject:2908 Change-Id: I056aeb6eddfba8757a139934c1cf68e00e860de6 Reviewed-on: https://chromium-review.googlesource.com/c/1296952 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 6165602f
...@@ -13,9 +13,17 @@ class ANGLE_EXPORT Timer ...@@ -13,9 +13,17 @@ class ANGLE_EXPORT Timer
{ {
public: public:
virtual ~Timer() {} virtual ~Timer() {}
// Timer functionality: Use start() and stop() to record the duration and use getElapsedTime()
// to query that duration. If getElapsedTime() is called in between, it will report the elapsed
// time since start().
virtual void start() = 0; virtual void start() = 0;
virtual void stop() = 0; virtual void stop() = 0;
virtual double getElapsedTime() const = 0; virtual double getElapsedTime() const = 0;
// Timestamp functionality: Use getAbsoluteTime() to get an absolute time with an unknown
// origin. This time moves forward regardless of start()/stop().
virtual double getAbsoluteTime() = 0;
}; };
ANGLE_EXPORT Timer *CreateTimer(); ANGLE_EXPORT Timer *CreateTimer();
......
...@@ -14,33 +14,46 @@ LinuxTimer::LinuxTimer() ...@@ -14,33 +14,46 @@ LinuxTimer::LinuxTimer()
{ {
} }
namespace
{
uint64_t getCurrentTimeNs()
{
struct timespec currentTime;
clock_gettime(CLOCK_MONOTONIC, &currentTime);
return currentTime.tv_sec * 1'000'000'000llu + currentTime.tv_nsec;
}
} // anonymous namespace
void LinuxTimer::start() void LinuxTimer::start()
{ {
clock_gettime(CLOCK_MONOTONIC, &mStartTime); mStartTimeNs = getCurrentTimeNs();
mRunning = true; mRunning = true;
} }
void LinuxTimer::stop() void LinuxTimer::stop()
{ {
clock_gettime(CLOCK_MONOTONIC, &mStopTime); mStopTimeNs = getCurrentTimeNs();
mRunning = false; mRunning = false;
} }
double LinuxTimer::getElapsedTime() const double LinuxTimer::getElapsedTime() const
{ {
struct timespec endTime; uint64_t endTimeNs;
if (mRunning) if (mRunning)
{ {
clock_gettime(CLOCK_MONOTONIC, &endTime); endTimeNs = getCurrentTimeNs();
} }
else else
{ {
endTime = mStopTime; endTimeNs = mStopTimeNs;
} }
double startSeconds = mStartTime.tv_sec + (1.0 / 1000000000) * mStartTime.tv_nsec; return (endTimeNs - mStartTimeNs) * 1e-9;
double endSeconds = endTime.tv_sec + (1.0 / 1000000000) * endTime.tv_nsec; }
return endSeconds - startSeconds;
double LinuxTimer::getAbsoluteTime()
{
return getCurrentTimeNs() * 1e-9;
} }
Timer *CreateTimer() Timer *CreateTimer()
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#ifndef UTIL_LINUX_TIMER_H #ifndef UTIL_LINUX_TIMER_H
#define UTIL_LINUX_TIMER_H #define UTIL_LINUX_TIMER_H
#include <stdint.h>
#include <time.h> #include <time.h>
#include "Timer.h" #include "Timer.h"
...@@ -22,10 +23,12 @@ class LinuxTimer : public Timer ...@@ -22,10 +23,12 @@ class LinuxTimer : public Timer
void stop() override; void stop() override;
double getElapsedTime() const override; double getElapsedTime() const override;
double getAbsoluteTime() override;
private: private:
bool mRunning; bool mRunning;
struct timespec mStartTime; uint64_t mStartTimeNs;
struct timespec mStopTime; uint64_t mStopTimeNs;
}; };
#endif // UTIL_LINUX_TIMER_H #endif // UTIL_LINUX_TIMER_H
...@@ -13,13 +13,30 @@ ...@@ -13,13 +13,30 @@
#include <mach/mach_time.h> #include <mach/mach_time.h>
OSXTimer::OSXTimer() OSXTimer::OSXTimer()
: mRunning(false) : mRunning(false),
mSecondCoeff(0)
{ {
} }
double OSXTimer::getSecondCoeff()
{
// If this is the first time we've run, get the timebase.
if (mSecondCoeff == 0.0)
{
mach_timebase_info_data_t timebaseInfo;
mach_timebase_info(&timebaseInfo);
mSecondCoeff = timebaseInfo.numer * (1.0 / 1000000000) / timebaseInfo.denom;
}
return mSecondCoeff;
}
void OSXTimer::start() void OSXTimer::start()
{ {
mStartTime = mach_absolute_time(); mStartTime = mach_absolute_time();
// Cache secondCoeff
getSecondCoeff();
mRunning = true; mRunning = true;
} }
...@@ -31,29 +48,21 @@ void OSXTimer::stop() ...@@ -31,29 +48,21 @@ void OSXTimer::stop()
double OSXTimer::getElapsedTime() const double OSXTimer::getElapsedTime() const
{ {
// If this is the first time we've run, get the timebase.
// We can use denom == 0 to indicate that sTimebaseInfo is
// uninitialised because it makes no sense to have a zero
// denominator in a fraction.
static mach_timebase_info_data_t timebaseInfo;
static double secondCoeff;
if ( timebaseInfo.denom == 0 )
{
mach_timebase_info(&timebaseInfo);
secondCoeff = timebaseInfo.numer * (1.0 / 1000000000) / timebaseInfo.denom;
}
if (mRunning) if (mRunning)
{ {
return secondCoeff * (mach_absolute_time() - mStartTime); return mSecondCoeff * (mach_absolute_time() - mStartTime);
} }
else else
{ {
return secondCoeff * (mStopTime - mStartTime); return mSecondCoeff * (mStopTime - mStartTime);
} }
} }
double OSXTimer::getAbsoluteTime()
{
return getSecondCoeff() * mach_absolute_time();
}
Timer *CreateTimer() Timer *CreateTimer()
{ {
return new OSXTimer(); return new OSXTimer();
......
...@@ -23,10 +23,15 @@ class OSXTimer : public Timer ...@@ -23,10 +23,15 @@ class OSXTimer : public Timer
void stop() override; void stop() override;
double getElapsedTime() const override; double getElapsedTime() const override;
double getAbsoluteTime() override;
private: private:
double getSecondCoeff();
bool mRunning; bool mRunning;
uint64_t mStartTime; uint64_t mStartTime;
uint64_t mStopTime; uint64_t mStopTime;
double mSecondCoeff;
}; };
#endif // UTIL_OSX_TIMER_H_ #endif // UTIL_OSX_TIMER_H_
...@@ -12,16 +12,28 @@ WindowsTimer::WindowsTimer() : mRunning(false), mStartTime(0), mStopTime(0) ...@@ -12,16 +12,28 @@ WindowsTimer::WindowsTimer() : mRunning(false), mStartTime(0), mStopTime(0)
{ {
} }
void WindowsTimer::start() LONGLONG WindowsTimer::getFrequency()
{ {
LARGE_INTEGER frequency; if (mFrequency == 0)
QueryPerformanceFrequency(&frequency); {
mFrequency = frequency.QuadPart; LARGE_INTEGER frequency = {};
QueryPerformanceFrequency(&frequency);
mFrequency = frequency.QuadPart;
}
return mFrequency;
}
void WindowsTimer::start()
{
LARGE_INTEGER curTime; LARGE_INTEGER curTime;
QueryPerformanceCounter(&curTime); QueryPerformanceCounter(&curTime);
mStartTime = curTime.QuadPart; mStartTime = curTime.QuadPart;
// Cache the frequency
getFrequency();
mRunning = true; mRunning = true;
} }
...@@ -51,6 +63,14 @@ double WindowsTimer::getElapsedTime() const ...@@ -51,6 +63,14 @@ double WindowsTimer::getElapsedTime() const
return static_cast<double>(endTime - mStartTime) / mFrequency; return static_cast<double>(endTime - mStartTime) / mFrequency;
} }
double WindowsTimer::getAbsoluteTime()
{
LARGE_INTEGER curTime;
QueryPerformanceCounter(&curTime);
return static_cast<double>(curTime.QuadPart) / getFrequency();
}
Timer *CreateTimer() Timer *CreateTimer()
{ {
return new WindowsTimer(); return new WindowsTimer();
......
...@@ -22,11 +22,14 @@ class WindowsTimer : public Timer ...@@ -22,11 +22,14 @@ class WindowsTimer : public Timer
void stop() override; void stop() override;
double getElapsedTime() const override; double getElapsedTime() const override;
double getAbsoluteTime() override;
private: private:
LONGLONG getFrequency();
bool mRunning; bool mRunning;
LONGLONG mStartTime; LONGLONG mStartTime;
LONGLONG mStopTime; LONGLONG mStopTime;
LONGLONG mFrequency; LONGLONG mFrequency;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment