Kaydet (Commit) 73bc3643 authored tarafından Jan-Marek Glogowski's avatar Jan-Marek Glogowski

Add tools::Time::GetMonotonicTicks (us)

This moves a combination of tools::Time::GetSystemTicks(), canvas
ElapsedTime::getSystemTime() and the opencl timing implementation
into tools::Time::GetMonotonicTicks() as a monotonic microsecond
time source.

Change-Id: I5c9263540b8af55b2eeca6126e288129427f6e8e
Reviewed-on: https://gerrit.libreoffice.org/41991Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarStephan Bergmann <sbergman@redhat.com>
üst cef9cf59
......@@ -69,10 +69,4 @@ $(eval $(call gb_Library_add_defs,canvastools,\
endif
endif
ifeq ($(OS),WNT)
$(eval $(call gb_Library_use_system_win32_libs,canvastools,\
winmm \
))
endif
# vim: set noet sw=4 ts=4:
......@@ -19,28 +19,9 @@
#include <sal/config.h>
#include <osl/time.h>
#include <canvas/elapsedtime.hxx>
#if defined(_WIN32)
#if defined _MSC_VER
#pragma warning(push,1)
#endif
// TEMP!!!
// Awaiting corresponding functionality in OSL
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winbase.h>
#include <mmsystem.h>
#endif
#if defined _MSC_VER
#pragma warning(pop)
#endif
#include <tools/time.hxx>
#include <algorithm>
#include <limits>
......@@ -48,69 +29,11 @@
namespace canvas {
namespace tools {
#if defined(_WIN32)
// TODO(Q2): is 0 okay for the failure case here?
double ElapsedTime::getSystemTime()
{
// TEMP!!!
// Awaiting corresponding functionality in OSL
// is there a performance counter available?
static bool bTimeSetupDone( false );
static bool bPerfTimerAvailable( false );
static LONGLONG nPerfCountFreq;
// TODO(F1): This _might_ cause problems, as it prevents correct
// time handling for very long lifetimes of this class's
// surrounding component in memory. When the difference between
// current sys time and nInitialCount exceeds IEEE double's
// mantissa, time will start to run jerky.
static LONGLONG nInitialCount;
if( !bTimeSetupDone )
{
if( QueryPerformanceFrequency(
reinterpret_cast<LARGE_INTEGER *>(&nPerfCountFreq) ) )
{
// read initial time:
QueryPerformanceCounter(
reinterpret_cast<LARGE_INTEGER *>(&nInitialCount) );
bPerfTimerAvailable = true;
}
bTimeSetupDone = true;
}
if( bPerfTimerAvailable )
{
LONGLONG nCurrCount;
QueryPerformanceCounter(
reinterpret_cast<LARGE_INTEGER *>(&nCurrCount) );
nCurrCount -= nInitialCount;
return double(nCurrCount) / nPerfCountFreq;
}
else
{
LONGLONG nCurrTime = timeGetTime();
return double(nCurrTime) / 1000.0;
}
return ::tools::Time::GetMonotonicTicks() / 1.0E6;
}
#else // ! WNT
// TODO(Q2): is 0 okay for the failure case here?
double ElapsedTime::getSystemTime()
{
TimeValue aTimeVal;
if( osl_getSystemTime( &aTimeVal ) )
return ((aTimeVal.Nanosec * 10e-10) + aTimeVal.Seconds);
else
return 0.0;
}
#endif
ElapsedTime::ElapsedTime()
: m_pTimeBase(),
m_fLastQueriedTime( 0.0 ),
......
......@@ -121,9 +121,27 @@ public:
static Time GetUTCOffset();
/// Elapsed time since epoch in milliseconds
/**
* Elapsed time in milliseconds (1e-3) since some unspecified starting point
*
* Convenience function, which just calls GetMonotonicTicks() / 1000.
*/
static sal_uInt64 GetSystemTicks();
/**
* Elapsed time in microseconds (1e-6) since some unspecified starting point
*
* Uses the high-precision, monotonic time sources provided by the OS, if
* available. Don't try to relate it to the system time, and also it's long
* time accuracy is not the best.
*
* Currently used to measure the runtime of OpenCL shaders and to set a
* message creation timestamp to allow filtering of invalid timer messages.
*
* @return current system ticks in microseconds (1e-6s)
*/
static sal_uInt64 GetMonotonicTicks();
tools::Time& operator =( const tools::Time& rTime );
Time operator -() const
{ return Time( -nTime ); }
......
......@@ -7,16 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifdef _WIN32
#include <prewin.h>
#include <postwin.h>
#elif defined __MACH__
#include <mach/mach_time.h>
#else
#include <sys/time.h>
#endif
#include <time.h>
#include <math.h>
#include <float.h>
#include <iostream>
......@@ -30,6 +20,7 @@
#include <opencl/platforminfo.hxx>
#include <sal/log.hxx>
#include <rtl/math.hxx>
#include <tools/time.hxx>
#include <opencl/OpenCLZone.hxx>
......@@ -63,15 +54,6 @@ struct LibreOfficeDeviceEvaluationIO
unsigned long outputSize;
};
struct timer
{
#ifdef _WIN32
LARGE_INTEGER start;
#else
long long start;
#endif
};
const char* source = STRINGIFY(
\n#if defined(KHR_DP_EXTENSION)
\n#pragma OPENCL EXTENSION cl_khr_fp64 : enable
......@@ -129,47 +111,6 @@ const char* source = STRINGIFY(
size_t sourceSize[] = { strlen(source) };
/*************************************************************************/
/* INTERNAL FUNCTIONS */
/*************************************************************************/
/* Timer functions - start timer */
void timerStart(timer* mytimer)
{
#ifdef _WIN32
QueryPerformanceCounter(&mytimer->start);
#elif defined __MACH__
mytimer->start = mach_absolute_time();
#else
struct timespec s;
clock_gettime(CLOCK_MONOTONIC, &s);
mytimer->start = (long long)s.tv_sec * (long long)1.0E6 + (long long)s.tv_nsec / (long long)1.0E3;
#endif
}
/* Timer functions - get current value */
double timerCurrent(timer const * mytimer)
{
#ifdef _WIN32
LARGE_INTEGER stop, frequency;
QueryPerformanceCounter(&stop);
QueryPerformanceFrequency(&frequency);
double time = ((double)(stop.QuadPart - mytimer->start.QuadPart) / frequency.QuadPart);
#elif defined __MACH__
static mach_timebase_info_data_t info = { 0, 0 };
if (info.numer == 0)
mach_timebase_info(&info);
long long stop = mach_absolute_time();
double time = ((stop - mytimer->start) * (double) info.numer / info.denom) / 1.0E9;
#else
struct timespec s;
long long stop;
clock_gettime(CLOCK_MONOTONIC, &s);
stop = (long long)s.tv_sec * (long long)1.0E6 + (long long)s.tv_nsec / (long long)1.0E3;
double time = ((double)(stop - mytimer->start) / 1.0E6);
#endif
return time;
}
/* Random number generator */
double random(double min, double max)
{
......@@ -283,8 +224,7 @@ ds_status evaluateScoreForDevice(ds_device& rDevice, std::unique_ptr<LibreOffice
else
{
/* Build program succeeded */
timer kernelTime;
timerStart(&kernelTime);
sal_uInt64 kernelTime = tools::Time::GetMonotonicTicks();
/* Run kernel */
cl_kernel clKernel = clCreateKernel(clProgram, "DynamicKernel", &clStatus);
......@@ -321,7 +261,7 @@ ds_status evaluateScoreForDevice(ds_device& rDevice, std::unique_ptr<LibreOffice
clReleaseMemObject(clResult);
clReleaseKernel(clKernel);
rDevice.fTime = timerCurrent(&kernelTime);
rDevice.fTime = tools::Time::GetMonotonicTicks() - kernelTime;
rDevice.bErrors = false;
}
......@@ -334,8 +274,7 @@ ds_status evaluateScoreForDevice(ds_device& rDevice, std::unique_ptr<LibreOffice
{
/* Evaluating an Native CPU device */
SAL_INFO("opencl.device", "Device: \"CPU\" (Native) evaluation...");
timer kernelTime;
timerStart(&kernelTime);
sal_uInt64 kernelTime = tools::Time::GetMonotonicTicks();
unsigned long j;
for (j = 0; j < testData->outputSize; j++)
......@@ -354,13 +293,13 @@ ds_status evaluateScoreForDevice(ds_device& rDevice, std::unique_ptr<LibreOffice
// Don't run for much longer than one second
if (j > 0 && j % 100 == 0)
{
rDevice.fTime = timerCurrent(&kernelTime);
rDevice.fTime = tools::Time::GetMonotonicTicks() - kernelTime;
if (rDevice.fTime >= 1)
break;
}
}
rDevice.fTime = timerCurrent(&kernelTime);
rDevice.fTime = tools::Time::GetMonotonicTicks() - kernelTime;
// Scale time to how long it would have taken to go all the way to outputSize
rDevice.fTime /= ((double) j / testData->outputSize);
......
......@@ -107,6 +107,7 @@ $(eval $(call gb_Library_use_system_win32_libs,tl,\
ole32 \
shell32 \
uuid \
winmm \
))
endif
......
......@@ -23,6 +23,7 @@
#if defined(_WIN32)
#include <windows.h>
#include <mmsystem.h>
#elif defined UNX
#include <unistd.h>
#include <limits.h>
......@@ -34,6 +35,7 @@
#ifdef __MACH__
#include <mach/clock.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#endif
#include <sal/log.hxx>
......@@ -411,30 +413,54 @@ Time tools::Time::GetUTCOffset()
sal_uInt64 tools::Time::GetSystemTicks()
{
#if defined(_WIN32)
static LARGE_INTEGER nTicksPerSecond;
static bool bTicksPerSecondInitialized = false;
if (!bTicksPerSecondInitialized)
{
QueryPerformanceFrequency(&nTicksPerSecond);
bTicksPerSecondInitialized = true;
}
return tools::Time::GetMonotonicTicks() / 1000;
}
LARGE_INTEGER nPerformanceCount;
QueryPerformanceCounter(&nPerformanceCount);
#ifdef _WIN32
static LARGE_INTEGER initPerformanceFrequency()
{
LARGE_INTEGER nTicksPerSecond = { 0 };
if (!QueryPerformanceFrequency(&nTicksPerSecond))
nTicksPerSecond.QuadPart = 0;
return nTicksPerSecond;
}
#endif
return static_cast<sal_uInt64>(
(nPerformanceCount.QuadPart*1000)/nTicksPerSecond.QuadPart);
#else
timeval tv;
int n = gettimeofday (&tv, nullptr);
if (n == -1) {
int e = errno;
SAL_WARN("tools.datetime", "gettimeofday failed: " << e);
sal_uInt64 tools::Time::GetMonotonicTicks()
{
#ifdef _WIN32
static const LARGE_INTEGER nTicksPerSecond = initPerformanceFrequency();
if (nTicksPerSecond.QuadPart > 0)
{
LARGE_INTEGER nPerformanceCount;
QueryPerformanceCounter(&nPerformanceCount);
return static_cast<sal_uInt64>(
( nPerformanceCount.QuadPart * 1000 * 1000 ) / nTicksPerSecond.QuadPart );
}
return static_cast<sal_uInt64>(tv.tv_sec) * 1000
+ static_cast<sal_uInt64>(tv.tv_usec) / 1000;
else
{
return static_cast<sal_uInt64>( timeGetTime() * 1000 );
}
#else
sal_uInt64 nMicroSeconds;
#ifdef __MACH__
static mach_timebase_info_data_t info = { 0, 0 };
if ( 0 == info.numer )
mach_timebase_info( &info );
nMicroSeconds = mach_absolute_time() * (double) (info.numer / info.denom) / 1000;
#else
#if defined(USE_CLOCK_GETTIME)
struct timespec currentTime;
clock_gettime( CLOCK_MONOTONIC, &currentTime );
nMicroSeconds = currentTime.tv_sec * 1000 * 1000 + currentTime.tv_nsec / 1000;
#else
struct timeval currentTime;
gettimeofday( &currentTime, nullptr );
nMicroSeconds = currentTime.tv_sec * 1000 * 1000 + currentTime.tv_usec;
#endif
#endif // __MACH__
return nMicroSeconds;
#endif // _WIN32
}
} /* namespace tools */
......
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