phobos/std/perf.d
2007-09-10 04:44:12 +00:00

1148 lines
30 KiB
D

/* /////////////////////////////////////////////////////////////////////////////
* File: perf.d
*
* Purpose: Performance measurement classes. These classes were ported
* over to D from the STLSoft (http://stlsoft.org/) C++ libraries,
* which were documented in the article "Win32 Performance
* Measurement Option", May 2003 issue of Windows Develper Network
* (http://www.windevnet.com/documents/win0305a/).
*
* Created 19th March 2004
* Updated: 18th July 2004
*
* www: http://www.digitalmars.com/
*
* Copyright (C) 2004 by Digital Mars
* All Rights Reserved
* Written by Matthew Wilson
* www.digitalmars.com
* License for redistribution is by either the Artistic License in artistic.txt,
* or the LGPL
*
* ////////////////////////////////////////////////////////////////////////// */
/** \file std/perf.d This file contains platform-independent performance classes */
module std.perf;
/// \brief Performance counter scope class generating template
///
/// This template declares the class PerformanceCounterScope which manages a
/// performance counter instance, scoping its measurement interval by virtue of
/// its supporting the RAII mechanism.
auto class PerformanceCounterScope(T)
{
/// \name Construction
/// @{
public:
/// Constructs an instance of the PerformanceCounterScope using a reference
/// to the parameterising performance counter class, whose measurement is
/// to be scoped. The measurement interval is commenced with a call to
/// <b>start()</b> on the managed counter instance.
this(T counter)
in
{
assert(null !is counter);
}
body
{
m_counter = counter;
m_counter.start();
}
/// The measurement interval is completed with a call to <b>stop()</b> on the
/// managed counter instance.
~this()
{
m_counter.stop();
}
/// Calls <b>stop()</b> on the managed counter instance, so that intermediate
/// timings can be taken.
void stop()
{
m_counter.stop();
}
/// Returns a reference to the managed counter instance.
T counter()
{
return m_counter;
}
/// @}
/// \name Members
/// @{
private:
T m_counter;
/// @}
// Not to be implemented
private:
this(PerformanceCounterScope rhs);
}
version(linux)
{
extern (C)
{
private struct timeval
{
int tv_sec; /*!< The number of seconds, since Jan. 1, 1970, in the time value. */
int tv_usec; /*!< The number of microseconds in the time value. */
};
private struct timezone
{
int tz_minuteswest; /*!< minutes west of Greenwich. */
int tz_dsttime; /*!< type of dst corrections to apply. */
};
private void gettimeofday(timeval *tv, timezone *tz);
}
/* ////////////////////////////////////////////////////////////////////////// */
/// \brief A performance counter that uses the most accurate measurement APIs available on the host machine
///
/// This class attempts to use the high performance hardware counter as its measurement resource, but failing
/// that it defaults to less accurate resources in order to guarantee that meaningful measurements are always
/// available to application code
///
/// \ingroup group_synsoft_linux_perf
class PerformanceCounter
{
/// \name Types
/// @{
private:
alias timeval epoch_type;
public:
/// \brief The interval type
///
/// The type of the interval measurement, a 64-bit signed integer
alias long interval_type;
/// \brief The scope type
///
/// The type with which instances of the counter class can be subject to the RAII mechanism in order
/// to scope particular measurement intervals
alias PerformanceCounterScope!(PerformanceCounter) scope_type;
/// @}
/// \name Operations
/// @{
public:
/// \brief Starts measurement
///
/// Begins the measurement period
void start()
{
timezone tz;
gettimeofday(&m_start, &tz);
}
/// \brief Ends measurement
///
/// Ends the measurement period
void stop()
{
timezone tz;
gettimeofday(&m_end, &tz);
}
/// @}
/// \name Attributes
/// @{
public:
/// \brief The elapsed count in the measurement period
///
/// This represents the extent, in machine-specific increments, of the measurement period
interval_type periodCount()
{
return microseconds;
}
/// \brief The number of whole seconds in the measurement period
///
/// This represents the extent, in whole seconds, of the measurement period
interval_type seconds()
{
interval_type start = cast(interval_type)m_start.tv_sec + cast(interval_type)m_start.tv_usec / (1000 * 1000);
interval_type end = cast(interval_type)m_end.tv_sec + cast(interval_type)m_end.tv_usec / (1000 * 1000);
return end - start;
}
/// \brief The number of whole milliseconds in the measurement period
///
/// This represents the extent, in whole milliseconds, of the measurement period
interval_type milliseconds()
{
interval_type start = cast(interval_type)m_start.tv_sec * 1000 + cast(interval_type)m_start.tv_usec / 1000;
interval_type end = cast(interval_type)m_end.tv_sec * 1000 + cast(interval_type)m_end.tv_usec / 1000;
return end - start;
}
/// \brief The number of whole microseconds in the measurement period
///
/// This represents the extent, in whole microseconds, of the measurement period
interval_type microseconds()
{
interval_type start = cast(interval_type)m_start.tv_sec * 1000 * 1000 + cast(interval_type)m_start.tv_usec;
interval_type end = cast(interval_type)m_end.tv_sec * 1000 * 1000 + cast(interval_type)m_end.tv_usec;
return end - start;
}
/// @}
/// \name Members
/// @{
private:
epoch_type m_start; // start of measurement period
epoch_type m_end; // End of measurement period
/// @}
}
unittest
{
alias PerformanceCounter counter_type;
counter_type counter = new counter_type();
counter.start();
volatile for(int i = 0; i < 10000000; ++i)
{ }
counter.stop();
counter_type.interval_type us1 = counter.microseconds();
counter_type.interval_type ms1 = counter.milliseconds();
counter_type.interval_type s1 = counter.seconds();
volatile for(int i = 0; i < 10000000; ++i)
{ }
counter.stop();
counter_type.interval_type us2 = counter.microseconds();
counter_type.interval_type ms2 = counter.milliseconds();
counter_type.interval_type s2 = counter.seconds();
assert(us2 >= us1);
assert(ms2 >= ms1);
assert(s2 >= s1);
}
/* ////////////////////////////////////////////////////////////////////////// */
}
else version(Windows)
{
private import std.c.windows.windows;
/* ////////////////////////////////////////////////////////////////////////// */
/// \defgroup group_synsoft_win32_perf synsoft.win32.perf
/// \ingroup group_synsoft_win32
/// \brief This library provides Win32 Performance facilities
/* ////////////////////////////////////////////////////////////////////////// */
/// \brief A performance counter that uses the high performance hardware counter on the host machine
///
/// This class provides high-resolution performance monitoring using the host machine's high performance
/// hardware counter. This class does not provide meaningful timing information on operating systems
/// that do not provide a high performance hardware counter.
///
/// \ingroup group_synsoft_win32_perf
class HighPerformanceCounter
{
/// \name Types
/// @{
private:
alias long epoch_type;
public:
/// \brief The interval type
///
/// The type of the interval measurement, a 64-bit signed integer
alias long interval_type;
/// \brief The scope type
///
/// The type with which instances of the counter class can be subject to the RAII mechanism in order
/// to scope particular measurement intervals
alias PerformanceCounterScope!(HighPerformanceCounter) scope_type;
/// @}
/// \name Construction
/// @{
private:
static this()
{
if(!QueryPerformanceFrequency(&sm_freq))
{
sm_freq = 0x7fffffffffffffffL;
}
}
/// @}
/// \name Operations
/// @{
public:
/// \brief Starts measurement
///
/// Begins the measurement period
void start()
{
QueryPerformanceCounter(&m_start);
}
/// \brief Ends measurement
///
/// Ends the measurement period
void stop()
{
QueryPerformanceCounter(&m_end);
}
/// @}
/// \name Attributes
/// @{
public:
/// \brief The elapsed count in the measurement period
///
/// This represents the extent, in machine-specific increments, of the measurement period
interval_type periodCount()
{
return m_end - m_start;
}
/// \brief The number of whole seconds in the measurement period
///
/// This represents the extent, in whole seconds, of the measurement period
interval_type seconds()
{
return periodCount() / sm_freq;
}
/// \brief The number of whole milliseconds in the measurement period
///
/// This represents the extent, in whole milliseconds, of the measurement period
interval_type milliseconds()
{
interval_type result;
interval_type count = periodCount();
if(count < 0x20C49BA5E353F7L)
{
result = (count * 1000) / sm_freq;
}
else
{
result = (count / sm_freq) * 1000;
}
return result;
}
/// \brief The number of whole microseconds in the measurement period
///
/// This represents the extent, in whole microseconds, of the measurement period
interval_type microseconds()
{
interval_type result;
interval_type count = periodCount();
if(count < 0x8637BD05AF6L)
{
result = (count * 1000000) / sm_freq;
}
else
{
result = (count / sm_freq) * 1000000;
}
return result;
}
/// @}
/// \name Members
/// @{
private:
epoch_type m_start; // start of measurement period
epoch_type m_end; // End of measurement period
static interval_type sm_freq; // Frequency
/// @}
}
unittest
{
alias HighPerformanceCounter counter_type;
counter_type counter = new counter_type();
counter.start();
volatile for(int i = 0; i < 10000000; ++i)
{ }
counter.stop();
counter_type.interval_type us1 = counter.microseconds();
counter_type.interval_type ms1 = counter.milliseconds();
counter_type.interval_type s1 = counter.seconds();
volatile for(int i = 0; i < 10000000; ++i)
{ }
counter.stop();
counter_type.interval_type us2 = counter.microseconds();
counter_type.interval_type ms2 = counter.milliseconds();
counter_type.interval_type s2 = counter.seconds();
assert(us2 >= us1);
assert(ms2 >= ms1);
assert(s2 >= s1);
}
/* ////////////////////////////////////////////////////////////////////////// */
/// \brief A low-cost, low-resolution performance counter
///
/// This class provides low-resolution, but low-latency, performance monitoring
/// and is guaranteed to be meaningful on all operating systems.
///
/// \ingroup group_synsoft_win32_perf
class TickCounter
{
/// \name Types
/// @{
private:
alias long epoch_type;
public:
/// \brief The interval type
///
/// The type of the interval measurement, a 64-bit signed integer
alias long interval_type;
/// \brief The scope type
///
/// The type with which instances of the counter class can be subject to the RAII mechanism in order
/// to scope particular measurement intervals
alias PerformanceCounterScope!(TickCounter) scope_type;
/// @}
/// \name Construction
/// @{
public:
/// @}
/// \name Operations
/// @{
public:
/// \brief Starts measurement
///
/// Begins the measurement period
void start()
{
m_start = GetTickCount();
}
/// \brief Ends measurement
///
/// Ends the measurement period
void stop()
{
m_end = GetTickCount();
}
/// @}
/// \name Attributes
/// @{
public:
/// \brief The elapsed count in the measurement period
///
/// This represents the extent, in machine-specific increments, of the measurement period
interval_type periodCount()
{
return m_end - m_start;
}
/// \brief The number of whole seconds in the measurement period
///
/// This represents the extent, in whole seconds, of the measurement period
interval_type seconds()
{
return periodCount() / 1000;
}
/// \brief The number of whole milliseconds in the measurement period
///
/// This represents the extent, in whole milliseconds, of the measurement period
interval_type milliseconds()
{
return periodCount();
}
/// \brief The number of whole microseconds in the measurement period
///
/// This represents the extent, in whole microseconds, of the measurement period
interval_type microseconds()
{
return periodCount() * 1000;
}
/// @}
/// \name Members
/// @{
private:
uint m_start; // start of measurement period
uint m_end; // End of measurement period
/// @}
}
unittest
{
alias TickCounter counter_type;
counter_type counter = new counter_type();
counter.start();
volatile for(int i = 0; i < 10000000; ++i)
{ }
counter.stop();
counter_type.interval_type us1 = counter.microseconds();
counter_type.interval_type ms1 = counter.milliseconds();
counter_type.interval_type s1 = counter.seconds();
volatile for(int i = 0; i < 10000000; ++i)
{ }
counter.stop();
counter_type.interval_type us2 = counter.microseconds();
counter_type.interval_type ms2 = counter.milliseconds();
counter_type.interval_type s2 = counter.seconds();
assert(us2 >= us1);
assert(ms2 >= ms1);
assert(s2 >= s1);
}
/* ////////////////////////////////////////////////////////////////////////// */
/// \brief A performance counter that provides thread-specific performance timings
///
/// This class uses the operating system's performance monitoring facilities to provide timing
/// information pertaining to the calling thread only, irrespective of the activities of other
/// threads on the system. This class does not provide meaningful timing information on operating
/// systems that do not provide thread-specific monitoring.
///
/// \ingroup group_synsoft_win32_perf
class ThreadTimesCounter
{
/// \name Types
/// @{
private:
alias long epoch_type;
public:
/// \brief The interval type
///
/// The type of the interval measurement, a 64-bit signed integer
alias long interval_type;
/// \brief The scope type
///
/// The type with which instances of the counter class can be subject to the RAII mechanism in order
/// to scope particular measurement intervals
alias PerformanceCounterScope!(ThreadTimesCounter) scope_type;
/// @}
/// \name Construction
/// @{
public:
/// \brief Constructor
///
/// Creates an instance of the class, and caches the thread token so that measurements will
/// be taken with respect to the thread in which the class was created.
this()
{
m_thread = GetCurrentThread();
}
/// @}
/// \name Operations
/// @{
public:
/// \brief Starts measurement
///
/// Begins the measurement period
void start()
{
FILETIME creationTime;
FILETIME exitTime;
GetThreadTimes(m_thread, &creationTime, &exitTime, cast(FILETIME*)&m_kernelStart, cast(FILETIME*)&m_userStart);
}
/// \brief Ends measurement
///
/// Ends the measurement period
void stop()
{
FILETIME creationTime;
FILETIME exitTime;
GetThreadTimes(m_thread, &creationTime, &exitTime, cast(FILETIME*)&m_kernelEnd, cast(FILETIME*)&m_userEnd);
}
/// @}
/// \name Attributes
/// @{
public:
/// \name Kernel
/// @{
/// \brief The elapsed count in the measurement period for kernel mode activity
///
/// This represents the extent, in machine-specific increments, of the measurement period for kernel mode activity
interval_type kernelPeriodCount()
{
return m_kernelEnd - m_kernelStart;
}
/// \brief The number of whole seconds in the measurement period for kernel mode activity
///
/// This represents the extent, in whole seconds, of the measurement period for kernel mode activity
interval_type kernelSeconds()
{
return kernelPeriodCount() / 10000000;
}
/// \brief The number of whole milliseconds in the measurement period for kernel mode activity
///
/// This represents the extent, in whole milliseconds, of the measurement period for kernel mode activity
interval_type kernelMilliseconds()
{
return kernelPeriodCount() / 10000;
}
/// \brief The number of whole microseconds in the measurement period for kernel mode activity
///
/// This represents the extent, in whole microseconds, of the measurement period for kernel mode activity
interval_type kernelMicroseconds()
{
return kernelPeriodCount() / 10;
}
/// @}
/// \name User
/// @{
/// \brief The elapsed count in the measurement period for user mode activity
///
/// This represents the extent, in machine-specific increments, of the measurement period for user mode activity
interval_type userPeriodCount()
{
return m_userEnd - m_userStart;
}
/// \brief The number of whole seconds in the measurement period for user mode activity
///
/// This represents the extent, in whole seconds, of the measurement period for user mode activity
interval_type userSeconds()
{
return userPeriodCount() / 10000000;
}
/// \brief The number of whole milliseconds in the measurement period for user mode activity
///
/// This represents the extent, in whole milliseconds, of the measurement period for user mode activity
interval_type userMilliseconds()
{
return userPeriodCount() / 10000;
}
/// \brief The number of whole microseconds in the measurement period for user mode activity
///
/// This represents the extent, in whole microseconds, of the measurement period for user mode activity
interval_type userMicroseconds()
{
return userPeriodCount() / 10;
}
/// @}
/// \name Total
/// @{
/// \brief The elapsed count in the measurement period
///
/// This represents the extent, in machine-specific increments, of the measurement period
interval_type periodCount()
{
return kernelPeriodCount() + userPeriodCount();
}
/// \brief The number of whole seconds in the measurement period
///
/// This represents the extent, in whole seconds, of the measurement period
interval_type seconds()
{
return periodCount() / 10000000;
}
/// \brief The number of whole milliseconds in the measurement period
///
/// This represents the extent, in whole milliseconds, of the measurement period
interval_type milliseconds()
{
return periodCount() / 10000;
}
/// \brief The number of whole microseconds in the measurement period
///
/// This represents the extent, in whole microseconds, of the measurement period
interval_type microseconds()
{
return periodCount() / 10;
}
/// @}
/// @}
/// \name Members
/// @{
private:
epoch_type m_kernelStart;
epoch_type m_kernelEnd;
epoch_type m_userStart;
epoch_type m_userEnd;
HANDLE m_thread;
/// @}
}
unittest
{
alias ThreadTimesCounter counter_type;
counter_type counter = new counter_type();
counter.start();
volatile for(int i = 0; i < 10000000; ++i)
{ }
counter.stop();
counter_type.interval_type us1 = counter.microseconds();
counter_type.interval_type ms1 = counter.milliseconds();
counter_type.interval_type s1 = counter.seconds();
volatile for(int i = 0; i < 10000000; ++i)
{ }
counter.stop();
counter_type.interval_type us2 = counter.microseconds();
counter_type.interval_type ms2 = counter.milliseconds();
counter_type.interval_type s2 = counter.seconds();
assert(us2 >= us1);
assert(ms2 >= ms1);
assert(s2 >= s1);
}
/* ////////////////////////////////////////////////////////////////////////// */
/// \brief A performance counter that provides process-specific performance timings
///
/// This class uses the operating system's performance monitoring facilities to provide timing
/// information pertaining to the calling process only, irrespective of the activities of other
/// processes on the system. This class does not provide meaningful timing information on operating
/// systems that do not provide process-specific monitoring.
///
/// \ingroup group_synsoft_win32_perf
class ProcessTimesCounter
{
/// \name Types
/// @{
private:
alias long epoch_type;
public:
/// \brief The interval type
///
/// The type of the interval measurement, a 64-bit signed integer
alias long interval_type;
/// \brief The scope type
///
/// The type with which instances of the counter class can be subject to the RAII mechanism in order
/// to scope particular measurement intervals
alias PerformanceCounterScope!(ProcessTimesCounter) scope_type;
/// @}
/// \name Construction
/// @{
private:
/// \brief Class constructor
///
/// Detects availability of the high performance hardware counter, and if
/// not available adjusts
static this()
{
sm_process = GetCurrentProcess();
}
/// @}
/// \name Operations
/// @{
public:
/// \brief Starts measurement
///
/// Begins the measurement period
void start()
{
FILETIME creationTime;
FILETIME exitTime;
GetProcessTimes(sm_process, &creationTime, &exitTime, cast(FILETIME*)&m_kernelStart, cast(FILETIME*)&m_userStart);
}
/// \brief Ends measurement
///
/// Ends the measurement period
void stop()
{
FILETIME creationTime;
FILETIME exitTime;
GetProcessTimes(sm_process, &creationTime, &exitTime, cast(FILETIME*)&m_kernelEnd, cast(FILETIME*)&m_userEnd);
}
/// @}
/// \name Attributes
/// @{
public:
/// \name Kernel
/// @{
/// \brief The elapsed count in the measurement period for kernel mode activity
///
/// This represents the extent, in machine-specific increments, of the measurement period for kernel mode activity
interval_type kernelPeriodCount()
{
return m_kernelEnd - m_kernelStart;
}
/// \brief The number of whole seconds in the measurement period for kernel mode activity
///
/// This represents the extent, in whole seconds, of the measurement period for kernel mode activity
interval_type kernelSeconds()
{
return kernelPeriodCount() / 10000000;
}
/// \brief The number of whole milliseconds in the measurement period for kernel mode activity
///
/// This represents the extent, in whole milliseconds, of the measurement period for kernel mode activity
interval_type kernelMilliseconds()
{
return kernelPeriodCount() / 10000;
}
/// \brief The number of whole microseconds in the measurement period for kernel mode activity
///
/// This represents the extent, in whole microseconds, of the measurement period for kernel mode activity
interval_type kernelMicroseconds()
{
return kernelPeriodCount() / 10;
}
/// @}
/// \name User
/// @{
/// \brief The elapsed count in the measurement period for user mode activity
///
/// This represents the extent, in machine-specific increments, of the measurement period for user mode activity
interval_type userPeriodCount()
{
return m_userEnd - m_userStart;
}
/// \brief The number of whole seconds in the measurement period for user mode activity
///
/// This represents the extent, in whole seconds, of the measurement period for user mode activity
interval_type userSeconds()
{
return userPeriodCount() / 10000000;
}
/// \brief The number of whole milliseconds in the measurement period for user mode activity
///
/// This represents the extent, in whole milliseconds, of the measurement period for user mode activity
interval_type userMilliseconds()
{
return userPeriodCount() / 10000;
}
/// \brief The number of whole microseconds in the measurement period for user mode activity
///
/// This represents the extent, in whole microseconds, of the measurement period for user mode activity
interval_type userMicroseconds()
{
return userPeriodCount() / 10;
}
/// @}
/// \name Total
/// @{
/// \brief The elapsed count in the measurement period
///
/// This represents the extent, in machine-specific increments, of the measurement period
interval_type periodCount()
{
return kernelPeriodCount() + userPeriodCount();
}
/// \brief The number of whole seconds in the measurement period
///
/// This represents the extent, in whole seconds, of the measurement period
interval_type seconds()
{
return periodCount() / 10000000;
}
/// \brief The number of whole milliseconds in the measurement period
///
/// This represents the extent, in whole milliseconds, of the measurement period
interval_type milliseconds()
{
return periodCount() / 10000;
}
/// \brief The number of whole microseconds in the measurement period
///
/// This represents the extent, in whole microseconds, of the measurement period
interval_type microseconds()
{
return periodCount() / 10;
}
/// @}
/// @}
/// \name Members
/// @{
private:
epoch_type m_kernelStart;
epoch_type m_kernelEnd;
epoch_type m_userStart;
epoch_type m_userEnd;
static HANDLE sm_process;
/// @}
}
unittest
{
alias ProcessTimesCounter counter_type;
counter_type counter = new counter_type();
counter.start();
volatile for(int i = 0; i < 10000000; ++i)
{ }
counter.stop();
counter_type.interval_type us1 = counter.microseconds();
counter_type.interval_type ms1 = counter.milliseconds();
counter_type.interval_type s1 = counter.seconds();
volatile for(int i = 0; i < 10000000; ++i)
{ }
counter.stop();
counter_type.interval_type us2 = counter.microseconds();
counter_type.interval_type ms2 = counter.milliseconds();
counter_type.interval_type s2 = counter.seconds();
assert(us2 >= us1);
assert(ms2 >= ms1);
assert(s2 >= s1);
}
/* ////////////////////////////////////////////////////////////////////////// */
/// \brief A performance counter that uses the most accurate measurement APIs available on the host machine
///
/// This class attempts to use the high performance hardware counter as its measurement resource, but failing
/// that it defaults to less accurate resources in order to guarantee that meaningful measurements are always
/// available to application code
///
/// \ingroup group_synsoft_win32_perf
class PerformanceCounter
{
/// \name Types
/// @{
private:
alias long epoch_type;
public:
/// \brief The interval type
///
/// The type of the interval measurement, a 64-bit signed integer
alias long interval_type;
/// \brief The scope type
///
/// The type with which instances of the counter class can be subject to the RAII mechanism in order
/// to scope particular measurement intervals
alias PerformanceCounterScope!(PerformanceCounter) scope_type;
/// @}
/// \name Constructors
/// @{
private:
/// \brief Class constructor
///
/// Detects availability of the high performance hardware counter, and if
/// not available adjusts
static this()
{
if(QueryPerformanceFrequency(&sm_freq))
{
sm_fn = &_qpc;
}
else
{
sm_freq = 1000;
sm_fn = &_qtc;
}
}
/// @}
/// \name Operations
/// @{
public:
/// \brief Starts measurement
///
/// Begins the measurement period
void start()
{
sm_fn(m_start);
}
/// \brief Ends measurement
///
/// Ends the measurement period
void stop()
{
sm_fn(m_end);
}
/// @}
/// \name Attributes
/// @{
public:
/// \brief The elapsed count in the measurement period
///
/// This represents the extent, in machine-specific increments, of the measurement period
interval_type periodCount()
{
return m_end - m_start;
}
/// \brief The number of whole seconds in the measurement period
///
/// This represents the extent, in whole seconds, of the measurement period
interval_type seconds()
{
return periodCount() / sm_freq;
}
/// \brief The number of whole milliseconds in the measurement period
///
/// This represents the extent, in whole milliseconds, of the measurement period
interval_type milliseconds()
{
interval_type result;
interval_type count = periodCount();
if(count < 0x20C49BA5E353F7L)
{
result = (count * 1000) / sm_freq;
}
else
{
result = (count / sm_freq) * 1000;
}
return result;
}
/// \brief The number of whole microseconds in the measurement period
///
/// This represents the extent, in whole microseconds, of the measurement period
interval_type microseconds()
{
interval_type result;
interval_type count = periodCount();
if(count < 0x8637BD05AF6L)
{
result = (count * 1000000) / sm_freq;
}
else
{
result = (count / sm_freq) * 1000000;
}
return result;
}
/// @}
/// \name Implementation
/// @{
private:
alias void function(out epoch_type interval) measure_func;
static void _qpc(out epoch_type interval)
{
QueryPerformanceCounter(&interval);
}
static void _qtc(out epoch_type interval)
{
interval = GetTickCount();
}
/// @}
/// \name Members
/// @{
private:
epoch_type m_start; // start of measurement period
epoch_type m_end; // End of measurement period
static interval_type sm_freq; // Frequency
static measure_func sm_fn; // Measurement function
/// @}
}
unittest
{
alias PerformanceCounter counter_type;
counter_type counter = new counter_type();
counter.start();
volatile for(int i = 0; i < 10000000; ++i)
{ }
counter.stop();
counter_type.interval_type us1 = counter.microseconds();
counter_type.interval_type ms1 = counter.milliseconds();
counter_type.interval_type s1 = counter.seconds();
volatile for(int i = 0; i < 10000000; ++i)
{ }
counter.stop();
counter_type.interval_type us2 = counter.microseconds();
counter_type.interval_type ms2 = counter.milliseconds();
counter_type.interval_type s2 = counter.seconds();
assert(us2 >= us1);
assert(ms2 >= ms1);
assert(s2 >= s1);
}
/* ////////////////////////////////////////////////////////////////////////// */
}
else
{
const int platform_not_supported = 0;
static assert(platform_not_supported);
}