123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
|
/*******************************************************************************
copyright: Copyright (c) 2007 Kris Bell. All rights reserved
license: BSD style: $(LICENSE)
version: Feb 2007: Initial release
author: Kris
*******************************************************************************/
module tango.time.StopWatch;
private import tango.core.Exception;
/*******************************************************************************
*******************************************************************************/
version (Win32)
{
private extern (Windows)
{
int QueryPerformanceCounter (ulong *count);
int QueryPerformanceFrequency (ulong *frequency);
}
}
version (Posix)
{
private import tango.stdc.posix.sys.time;
}
/*******************************************************************************
Timer for measuring small intervals, such as the duration of a
subroutine or other reasonably small period.
---
StopWatch elapsed;
elapsed.start;
// do something
// ...
double i = elapsed.stop;
---
The measured interval is in units of seconds, using floating-
point to represent fractions. This approach is more flexible
than integer arithmetic since it migrates trivially to more
capable timer hardware (there no implicit granularity to the
measurable intervals, except the limits of fp representation)
StopWatch is accurate to the extent of what the underlying OS
supports. On linux systems, this accuracy is typically 1 us at
best. Win32 is generally more precise.
There is some minor overhead in using StopWatch, so take that into
account
*******************************************************************************/
public struct StopWatch
{
private ulong started;
private static double multiplier = 1.0 / 1_000_000.0;
version (Win32)
private static double microsecond;
/***********************************************************************
Start the timer
***********************************************************************/
void start ()
{
started = timer;
}
/***********************************************************************
Stop the timer and return elapsed duration since start()
***********************************************************************/
double stop ()
{
return multiplier * (timer - started);
}
/***********************************************************************
Return elapsed time since the last start() as microseconds
***********************************************************************/
@property ulong microsec ()
{
version (Posix)
return (timer - started);
version (Win32)
return cast(ulong) ((timer - started) * microsecond);
}
/***********************************************************************
Setup timing information for later use
***********************************************************************/
shared static this()
{
version (Win32)
{
ulong freq;
QueryPerformanceFrequency (&freq);
microsecond = 1_000_000.0 / freq;
multiplier = 1.0 / freq;
}
}
/***********************************************************************
Return the current time as an Interval
***********************************************************************/
@property private static ulong timer ()
{
version (Posix)
{
timeval tv;
if (gettimeofday (&tv, null))
throw new PlatformException ("Timer :: linux timer is not available");
return (cast(ulong) tv.tv_sec * 1_000_000) + tv.tv_usec;
}
version (Win32)
{
ulong now;
if (! QueryPerformanceCounter (&now))
throw new PlatformException ("high-resolution timer is not available");
return now;
}
}
}
/*******************************************************************************
*******************************************************************************/
debug (StopWatch)
{
import tango.io.Stdout;
void main()
{
StopWatch t;
t.start;
for (int i=0; i < 100_000_000; ++i)
{}
Stdout.format ("{:f9}", t.stop).newline;
}
}
|