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
{
public:
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 stop() = 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();
......
......@@ -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()
{
clock_gettime(CLOCK_MONOTONIC, &mStartTime);
mStartTimeNs = getCurrentTimeNs();
mRunning = true;
}
void LinuxTimer::stop()
{
clock_gettime(CLOCK_MONOTONIC, &mStopTime);
mStopTimeNs = getCurrentTimeNs();
mRunning = false;
}
double LinuxTimer::getElapsedTime() const
{
struct timespec endTime;
uint64_t endTimeNs;
if (mRunning)
{
clock_gettime(CLOCK_MONOTONIC, &endTime);
endTimeNs = getCurrentTimeNs();
}
else
{
endTime = mStopTime;
endTimeNs = mStopTimeNs;
}
double startSeconds = mStartTime.tv_sec + (1.0 / 1000000000) * mStartTime.tv_nsec;
double endSeconds = endTime.tv_sec + (1.0 / 1000000000) * endTime.tv_nsec;
return endSeconds - startSeconds;
return (endTimeNs - mStartTimeNs) * 1e-9;
}
double LinuxTimer::getAbsoluteTime()
{
return getCurrentTimeNs() * 1e-9;
}
Timer *CreateTimer()
......
......@@ -9,6 +9,7 @@
#ifndef UTIL_LINUX_TIMER_H
#define UTIL_LINUX_TIMER_H
#include <stdint.h>
#include <time.h>
#include "Timer.h"
......@@ -22,10 +23,12 @@ class LinuxTimer : public Timer
void stop() override;
double getElapsedTime() const override;
double getAbsoluteTime() override;
private:
bool mRunning;
struct timespec mStartTime;
struct timespec mStopTime;
uint64_t mStartTimeNs;
uint64_t mStopTimeNs;
};
#endif // UTIL_LINUX_TIMER_H
......@@ -13,13 +13,30 @@
#include <mach/mach_time.h>
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()
{
mStartTime = mach_absolute_time();
// Cache secondCoeff
getSecondCoeff();
mRunning = true;
}
......@@ -31,29 +48,21 @@ void OSXTimer::stop()
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)
{
return secondCoeff * (mach_absolute_time() - mStartTime);
return mSecondCoeff * (mach_absolute_time() - mStartTime);
}
else
{
return secondCoeff * (mStopTime - mStartTime);
return mSecondCoeff * (mStopTime - mStartTime);
}
}
double OSXTimer::getAbsoluteTime()
{
return getSecondCoeff() * mach_absolute_time();
}
Timer *CreateTimer()
{
return new OSXTimer();
......
......@@ -23,10 +23,15 @@ class OSXTimer : public Timer
void stop() override;
double getElapsedTime() const override;
double getAbsoluteTime() override;
private:
double getSecondCoeff();
bool mRunning;
uint64_t mStartTime;
uint64_t mStopTime;
double mSecondCoeff;
};
#endif // UTIL_OSX_TIMER_H_
......@@ -12,16 +12,28 @@ WindowsTimer::WindowsTimer() : mRunning(false), mStartTime(0), mStopTime(0)
{
}
void WindowsTimer::start()
LONGLONG WindowsTimer::getFrequency()
{
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
mFrequency = frequency.QuadPart;
if (mFrequency == 0)
{
LARGE_INTEGER frequency = {};
QueryPerformanceFrequency(&frequency);
mFrequency = frequency.QuadPart;
}
return mFrequency;
}
void WindowsTimer::start()
{
LARGE_INTEGER curTime;
QueryPerformanceCounter(&curTime);
mStartTime = curTime.QuadPart;
// Cache the frequency
getFrequency();
mRunning = true;
}
......@@ -51,6 +63,14 @@ double WindowsTimer::getElapsedTime() const
return static_cast<double>(endTime - mStartTime) / mFrequency;
}
double WindowsTimer::getAbsoluteTime()
{
LARGE_INTEGER curTime;
QueryPerformanceCounter(&curTime);
return static_cast<double>(curTime.QuadPart) / getFrequency();
}
Timer *CreateTimer()
{
return new WindowsTimer();
......
......@@ -22,11 +22,14 @@ class WindowsTimer : public Timer
void stop() override;
double getElapsedTime() const override;
double getAbsoluteTime() override;
private:
LONGLONG getFrequency();
bool mRunning;
LONGLONG mStartTime;
LONGLONG mStopTime;
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