Commit c0461976 authored by pcapriotti's avatar pcapriotti
Browse files

Move getMonotonicUSec from base to the RTS.

parent d7bb8cd2
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
#include "BeginPrivate.h" #include "BeginPrivate.h"
void initializeTimer (void);
StgWord64 getMonotonicNSec (void);
Time getProcessCPUTime (void); Time getProcessCPUTime (void);
Time getThreadCPUTime (void); Time getThreadCPUTime (void);
Time getProcessElapsedTime (void); Time getProcessElapsedTime (void);
......
...@@ -1283,6 +1283,7 @@ typedef struct _RtsSymbolVal { ...@@ -1283,6 +1283,7 @@ typedef struct _RtsSymbolVal {
SymI_HasProto(n_capabilities) \ SymI_HasProto(n_capabilities) \
SymI_HasProto(stg_traceCcszh) \ SymI_HasProto(stg_traceCcszh) \
SymI_HasProto(stg_traceEventzh) \ SymI_HasProto(stg_traceEventzh) \
SymI_HasProto(getMonotonicNSec) \
RTS_USER_SIGNALS_SYMBOLS \ RTS_USER_SIGNALS_SYMBOLS \
RTS_INTCHAR_SYMBOLS RTS_INTCHAR_SYMBOLS
......
...@@ -128,6 +128,9 @@ hs_init_ghc(int *argc, char **argv[], RtsConfig rts_config) ...@@ -128,6 +128,9 @@ hs_init_ghc(int *argc, char **argv[], RtsConfig rts_config)
/* Initialise the stats department, phase 0 */ /* Initialise the stats department, phase 0 */
initStats0(); initStats0();
/* Initialize system timer before starting to collect stats */
initializeTimer();
/* Next we do is grab the start time...just in case we're /* Next we do is grab the start time...just in case we're
* collecting timing statistics. * collecting timing statistics.
*/ */
......
...@@ -33,6 +33,19 @@ ...@@ -33,6 +33,19 @@
// we'll implement getProcessCPUTime() and getProcessElapsedTime() // we'll implement getProcessCPUTime() and getProcessElapsedTime()
// separately, using getrusage() and gettimeofday() respectively // separately, using getrusage() and gettimeofday() respectively
#ifdef darwin_HOST_OS
static double timer_scaling_factor_ns = 0.0;
#endif
void initializeTimer()
{
#ifdef darwin_HOST_OS
mach_timebase_info_data_t info;
(void) mach_timebase_info(&info);
timer_scaling_factor_ns = (double)info.numer / (double)info.denom * 1e9;
#endif
}
Time getProcessCPUTime(void) Time getProcessCPUTime(void)
{ {
#if !defined(BE_CONSERVATIVE) && defined(HAVE_CLOCK_GETTIME) && defined (_SC_CPUTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) && defined(HAVE_SYSCONF) #if !defined(BE_CONSERVATIVE) && defined(HAVE_CLOCK_GETTIME) && defined (_SC_CPUTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) && defined(HAVE_SYSCONF)
...@@ -64,32 +77,31 @@ Time getProcessCPUTime(void) ...@@ -64,32 +77,31 @@ Time getProcessCPUTime(void)
} }
} }
Time getProcessElapsedTime(void) StgWord64 getMonotonicNSec(void)
{ {
#ifdef HAVE_CLOCK_GETTIME #ifdef HAVE_CLOCK_GETTIME
struct timespec ts; struct timespec ts;
clock_gettime(CLOCK_ID, &ts); clock_gettime(CLOCK_ID, &ts);
return SecondsToTime(ts.tv_sec) + NSToTime(ts.tv_nsec); return (StgWord64)ts.tv_sec * 1000000000 +
(StgWord64)ts.tv_nsec;
#elif defined(darwin_HOST_OS) #elif defined(darwin_HOST_OS)
uint64_t time = mach_absolute_time(); uint64_t time = mach_absolute_time();
static double scaling_factor = 0.0; return (double)time * timer_scaling_factor_ns;
if (scaling_factor == 0.0) {
mach_timebase_info_data_t info;
(void) mach_timebase_info(&info);
scaling_factor = (double)info.numer / (double)info.denom;
}
return (Time)((double)time * scaling_factor);
#else #else
struct timeval tv; struct timeval tv;
gettimeofday(&tv, (struct timezone *) NULL); gettimeofday(&tv, (struct timezone *) NULL);
return SecondsToTime(tv.tv_sec) + USToTime(tv.tv_usec); return (StgWord64)tv.tv_sec * 1000000000 +
(StgWord64)tv.tv_usec * 1000;
#endif #endif
} }
Time getProcessElapsedTime(void)
{
return NSToTime(getMonotonicNSec());
}
void getProcessTimes(Time *user, Time *elapsed) void getProcessTimes(Time *user, Time *elapsed)
{ {
*user = getProcessCPUTime(); *user = getProcessCPUTime();
......
...@@ -47,37 +47,57 @@ getProcessCPUTime(void) ...@@ -47,37 +47,57 @@ getProcessCPUTime(void)
return fileTimeToRtsTime(userTime); return fileTimeToRtsTime(userTime);
} }
// getProcessElapsedTime relies on QueryPerformanceFrequency // Number of ticks per second used by the QueryPerformanceFrequency
// which should be available on any Windows computer thay you // implementaiton, represented by a 64-bit union type.
// would want to run Haskell on. Satnam Singh, 5 July 2010. static LARGE_INTEGER qpc_frequency = {.QuadPart = 0};
// Initialize qpc_frequency. This function should be called before any call to
// getMonotonicNSec. If QPC is not supported on this system, qpc_frequency is
// set to 0.
void initializeTimer()
{
BOOL qpc_supported = QueryPerformanceFrequency(&qpc_frequency);
if (!qpc_supported)
{
qpc_frequency.QuadPart = 0;
}
}
HsWord64
getMonotonicNSec()
{
if (qpc_frequency.QuadPart)
{
// system_time is a 64-bit union type used to represent the
// tick count returned by QueryPerformanceCounter
LARGE_INTEGER system_time;
// get the tick count.
QueryPerformanceCounter(&system_time);
// compute elapsed seconds as double
double secs = (double)system_time.QuadPart /
(double)qpc_frequency.QuadPart;
// return elapsed time in nanoseconds
return (HsWord64)(secs * 1e9);
}
else // fallback to GetTickCount
{
// NOTE: GetTickCount is a 32-bit millisecond value, so it wraps around
// every 49 days.
DWORD count = GetTickCount();
// getTickCount is in milliseconds, so multiply it by 1000000 to get
// nanoseconds.
return (HsWord64)count * 1000000;
}
}
Time Time
getProcessElapsedTime(void) getProcessElapsedTime(void)
{ {
// frequency represents the number of ticks per second return NSToTime(getMonotonicNSec());
// used by the QueryPerformanceFrequency implementaiton
// and is represented by a 64-bit union type initially set to 0
// and updated just once (hence use of static).
static LARGE_INTEGER frequency = {.QuadPart = 0} ;
// system_time is a 64-bit union type used to represent the
// tick count returned by QueryPerformanceCounter
LARGE_INTEGER system_time ;
// If this is the first time we are calling getProcessElapsedTime
// then record the ticks per second used by QueryPerformanceCounter
if (frequency.QuadPart == 0) {
QueryPerformanceFrequency(&frequency);
}
// Get the tick count.
QueryPerformanceCounter(&system_time) ;
// Return the tick count as a Time value.
// Using double to compute the intermediate value, because a 64-bit
// int would overflow when multiplied by TICK_RESOLUTION in about 81 days.
return fsecondsToTime((double)system_time.QuadPart /
(double)frequency.QuadPart) ;
} }
Time Time
......
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