Expand Up
@@ -106,6 +106,7 @@ import core.stdc.time;
import std.array;
import std.algorithm;
import std.benchmark;
import std.conv;
import std.ctype;
import std.exception;
Expand All
@@ -119,6 +120,7 @@ import std.stdio;
import std.string;
import std.system;
import std.traits;
import std.typecons;
version(Windows)
{
Expand Down
Expand Up
@@ -275,19 +277,6 @@ enum PopFirst
yes
}
/++
Used by StopWatch to indicate whether it should start immediately upon
construction.
+/
enum AutoStart
{
/// No, don't start the StopWatch when it is constructed.
no,
/// Yes, do start the StopWatch when it is constructed.
yes
}
/++
Array of the strings representing time units, starting with the smallest
unit and going to the largest. It does not include $(D "nsecs").
Expand Down
Expand Up
@@ -30613,436 +30602,6 @@ unittest
}
//==============================================================================
// Section with StopWatch and Benchmark Code.
//==============================================================================
/++
$(D StopWatch) measures time as precisely as possible.
This class uses a high-performance counter. On Windows systems, it uses
$(D QueryPerformanceCounter), and on Posix systems, it uses
$(D clock_gettime) if available, and $(D gettimeofday) otherwise.
But the precision of $(D StopWatch) differs from system to system. It is
impossible to for it to be the same from system to system since the precision
of the system clock varies from system to system, and other system-dependent
and situation-dependent stuff (such as the overhead of a context switch
between threads) can also affect $(D StopWatch)'s accuracy.
Examples:
--------------------
void foo()
{
StopWatch sw;
enum n = 100;
TickDuration[n] times;
TickDuration last = TickDuration.from!"seconds"(0);
foreach(i; 0..n)
{
sw.start(); //start/resume mesuring.
foreach(unused; 0..1_000_000)
bar();
sw.stop(); //stop/pause measuring.
//Return value of peek() after having stopped are the always same.
writeln((i + 1) * 1_000_000, " times done, lap time: ",
sw.peek().msecs, "[ms]");
times[i] = sw.peek() - last;
last = sw.peek();
}
real sum = 0;
// When you want to know the number of seconds,
// you can use properties of TickDuration.
// (seconds, mseconds, useconds, hnsecs)
foreach(t; times)
sum += t.hnsecs;
writeln("Average time: ", sum/n, " hnsecs");
}
--------------------
+/
@safe struct StopWatch
{
public:
//Verify Example
@safe unittest
{
void writeln(S...)(S args){}
static void bar() {}
StopWatch sw;
enum n = 100;
TickDuration[n] times;
TickDuration last = TickDuration.from!"seconds"(0);
foreach(i; 0..n)
{
sw.start(); //start/resume mesuring.
foreach(unused; 0..1_000_000)
bar();
sw.stop(); //stop/pause measuring.
//Return value of peek() after having stopped are the always same.
writeln((i + 1) * 1_000_000, " times done, lap time: ",
sw.peek().msecs, "[ms]");
times[i] = sw.peek() - last;
last = sw.peek();
}
real sum = 0;
// When you want to know the number of seconds,
// you can use properties of TickDuration.
// (seconds, mseconds, useconds, hnsecs)
foreach(t; times)
sum += t.hnsecs;
writeln("Average time: ", sum/n, " hnsecs");
}
/++
Auto start with constructor.
+/
this(AutoStart autostart)
{
if(autostart)
start();
}
version(testStdDateTime) @safe unittest
{
auto sw = StopWatch(AutoStart.yes);
sw.stop();
}
///
bool opEquals(const ref StopWatch rhs) const pure nothrow
{
return _timeStart == rhs._timeStart &&
_timeMeasured == rhs._timeMeasured;
}
/++
Resets the stop watch.
+/
void reset()
{
if(_flagStarted)
{
// Set current system time if StopWatch is measuring.
_timeStart = Clock.currSystemTick;
}
else
{
// Set zero if StopWatch is not measuring.
_timeStart.length = 0;
}
_timeMeasured.length = 0;
}
version(testStdDateTime) @safe unittest
{
StopWatch sw;
sw.start();
sw.stop();
sw.reset();
assert(sw.peek().to!("seconds", real) == 0);
}
/++
Starts the stop watch.
+/
void start()
{
assert(!_flagStarted);
StopWatch sw;
_flagStarted = true;
_timeStart = Clock.currSystemTick;
}
version(testStdDateTime) @safe unittest
{
StopWatch sw;
sw.start();
auto t1 = sw.peek();
bool doublestart = true;
try
sw.start();
catch(AssertError e)
doublestart = false;
assert(!doublestart);
sw.stop();
assert((t1 - sw.peek()).to!("seconds", real) <= 0);
}
/++
Stops the stop watch.
+/
void stop()
{
assert(_flagStarted);
_flagStarted = false;
_timeMeasured += Clock.currSystemTick - _timeStart;
}
version(testStdDateTime) @safe unittest
{
StopWatch sw;
sw.start();
sw.stop();
auto t1 = sw.peek();
bool doublestop = true;
try
sw.stop();
catch(AssertError e)
doublestop = false;
assert(!doublestop);
assert((t1 - sw.peek()).to!("seconds", real) == 0);
}
/++
Peek at the amount of time which has passed since the stop watch was
started.
+/
TickDuration peek() const
{
if(_flagStarted)
return Clock.currSystemTick - _timeStart + _timeMeasured;
return _timeMeasured;
}
version(testStdDateTime) @safe unittest
{
StopWatch sw;
sw.start();
auto t1 = sw.peek();
sw.stop();
auto t2 = sw.peek();
auto t3 = sw.peek();
assert(t1 <= t2);
assert(t2 == t3);
}
private:
// true if observing.
bool _flagStarted = false;
// TickDuration at the time of StopWatch starting measurement.
TickDuration _timeStart;
// Total time that StopWatch ran.
TickDuration _timeMeasured;
}
// workaround for bug4886
@safe size_t lengthof(aliases...)() pure nothrow
{
return aliases.length;
}
/++
Benchmarks code for speed assessment and comparison.
Params:
fun = aliases of callable objects (e.g. function names). Each should
take no arguments.
n = The number of times each function is to be executed.
Returns:
The amount of time (as a $(CXREF time, TickDuration)) that it took to
call each function $(D n) times. The first value is the length of time
that it took to call $(D fun[0]) $(D n) times. The second value is the
length of time it took to call $(D fun[1]) $(D n) times. Etc.
Examples:
--------------------
int a;
void f0() {}
void f1() {auto b = a;}
void f2() {auto b = to!(string)(a);}
auto r = benchmark!(f0, f1, f2)(10_000_000);
writefln("Milliseconds to call fun[0] n times: %s", r[0].to!("msecs", int));
--------------------
+/
@safe TickDuration[lengthof!(fun)()] benchmark(fun...)(uint n)
if(areAllSafe!fun)
{
TickDuration[lengthof!(fun)()] result;
StopWatch sw;
sw.start();
foreach(i, unused; fun)
{
sw.reset();
foreach(j; 0 .. n)
fun[i]();
result[i] = sw.peek();
}
return result;
}
/++ Ditto +/
TickDuration[lengthof!(fun)()] benchmark(fun...)(uint times)
if(!areAllSafe!fun)
{
TickDuration[lengthof!(fun)()] result;
StopWatch sw;
sw.start();
foreach(i, unused; fun)
{
sw.reset();
foreach(j; 0 .. times)
fun[i]();
result[i] = sw.peek();
}
return result;
}
//Verify Examples.
version(testStdDateTime) unittest
{
void writefln(S...)(S args){}
int a;
void f0() {}
void f1() {auto b = a;}
void f2() {auto b = to!(string)(a);}
auto r = benchmark!(f0, f1, f2)(10_000_000);
writefln("Milliseconds to call fun[0] n times: %s", r[0].to!("msecs", int));
}
version(testStdDateTime) @safe unittest
{
int a;
void f0() {}
//void f1() {auto b = to!(string)(a);}
void f2() {auto b = (a);}
auto r = benchmark!(f0, f2)(100);
}
/++
Return value of benchmark with two functions comparing.
+/
@safe struct ComparingBenchmarkResult
{
/++
Evaluation value
This returns the evaluation value of performance as the ratio of
baseFunc's time over targetFunc's time. If performance is high, this
returns a high value.
+/
@property real point() const pure nothrow
{
return _baseTime.length / cast(const real)_targetTime.length;
}
/++
The time required of the base function
+/
@property public TickDuration baseTime() const pure nothrow
{
return _baseTime;
}
/++
The time required of the target function
+/
@property public TickDuration targetTime() const pure nothrow
{
return _targetTime;
}
private:
this(TickDuration baseTime, TickDuration targetTime) pure nothrow
{
_baseTime = baseTime;
_targetTime = targetTime;
}
TickDuration _baseTime;
TickDuration _targetTime;
}
/++
Benchmark with two functions comparing.
Params:
baseFunc = The function to become the base of the speed.
targetFunc = The function that wants to measure speed.
times = The number of times each function is to be executed.
Examples:
--------------------
void f1() {
// ...
}
void f2() {
// ...
}
void main() {
auto b = comparingBenchmark!(f1, f2, 0x80);
writeln(b.point);
}
--------------------
+/
@safe ComparingBenchmarkResult comparingBenchmark(alias baseFunc,
alias targetFunc,
int times = 0xfff)()
if(isSafe!baseFunc && isSafe!targetFunc)
{
auto t = benchmark!(baseFunc, targetFunc)(times);
return ComparingBenchmarkResult(t[0], t[1]);
}
/++ Ditto +/
ComparingBenchmarkResult comparingBenchmark(alias baseFunc,
alias targetFunc,
int times = 0xfff)()
if(!isSafe!baseFunc || !isSafe!targetFunc)
{
auto t = benchmark!(baseFunc, targetFunc)(times);
return ComparingBenchmarkResult(t[0], t[1]);
}
version(testStdDateTime) @safe unittest
{
void f1x() {}
void f2x() {}
@safe void f1o() {}
@safe void f2o() {}
auto b1 = comparingBenchmark!(f1o, f2o, 1); // OK
//static auto b2 = comparingBenchmark!(f1x, f2x, 1); // NG
}
version(testStdDateTime) unittest
{
void f1x() {}
void f2x() {}
@safe void f1o() {}
@safe void f2o() {}
auto b1 = comparingBenchmark!(f1o, f2o, 1); // OK
auto b2 = comparingBenchmark!(f1x, f2x, 1); // OK
}
//==============================================================================
// Section with public helper functions and templates.
//==============================================================================
Expand Down
Expand Up
@@ -32074,103 +31633,6 @@ unittest
}
version(StdDdoc)
{
/++
Function for starting to a stop watch time when the function is called
and stopping it when its return value goes out of scope and is destroyed.
When the value that is returned by this function is destroyed,
$(D func) will run. $(D func) is a unary function that takes a
$(CXREF TickDuration).
Examples:
--------------------
writeln("benchmark start!");
{
auto mt = measureTime!((a){assert(a.seconds);});
doSomething();
}
writeln("benchmark end!");
--------------------
+/
auto measureTime(alias func)();
}
else
{
@safe auto measureTime(alias func)()
if(isSafe!func)
{
struct Result
{
private StopWatch _sw = void;
this(AutoStart as)
{
_sw = StopWatch(as);
}
~this()
{
unaryFun!(func)(_sw.peek());
}
}
return Result(AutoStart.yes);
}
auto measureTime(alias func)()
if(!isSafe!func)
{
struct Result
{
private StopWatch _sw = void;
this(AutoStart as)
{
_sw = StopWatch(as);
}
~this()
{
unaryFun!(func)(_sw.peek());
}
}
return Result(AutoStart.yes);
}
}
version(testStdDateTime) @safe unittest
{
@safe static void func(TickDuration td)
{
assert(td.to!("seconds", real) <>= 0);
}
auto mt = measureTime!(func)();
/+
with (measureTime!((a){assert(a.seconds);}))
{
// doSomething();
// @@@BUG@@@ doesn't work yet.
}
+/
}
version(testStdDateTime) unittest
{
static void func(TickDuration td)
{
assert(td.to!("seconds", real) <>= 0);
}
auto mt = measureTime!(func)();
/+
with (measureTime!((a){assert(a.seconds);}))
{
// doSomething();
// @@@BUG@@@ doesn't work yet.
}
+/
}
//==============================================================================
// Private Section.
//==============================================================================
Expand Down