On Thursday, 23 June 2016 at 22:08:20 UTC, Seb wrote:
[1] https://github.com/wilzbach/perf-d/blob/master/test_pow.d
[2] https://github.com/wilzbach/perf-d/blob/master/test_powi.d

This is a bad way to benchmark. You are essentially testing the compiler's ability to propagate your constants into the benchmarking loop/hoisting the code to be benchmarked out of it.

For cross-compiler tests, you should define the candidate functions in a separate compilation units with an extern(C) interface to inhibit any optimisations. In this case, your code could e.g. be altered to:

---
import std.math : pow;
extern(C) long useStd(long a, long b) { return pow(a, b); }
extern(C) long useOp(long a, long b) { return a ^^ b; }
---
extern(C) long useStd(long a, long b);
extern(C) long useOp(long a, long b);

void main(string[] args)
{
    import std.datetime: benchmark, Duration;
    import std.stdio: writeln, writefln;
    import std.conv: to;

    long a = 5;
    long b = 25;
    long l = 0;

    void f0() { l += useStd(a, b); }
    void f1() { l += useOp(a, b); }

    auto rs = benchmark!(f0, f1)(100_000_000);

    foreach(j,r;rs)
    {
        version(GNU)
writefln("%d %d secs %d ms", j, r.seconds(), r.msecs());
        else
            writeln(j, " ", r.to!Duration);
    }

    // prevent any optimization
    writeln(l);
}
---
(Keeping track of the sum is of course no longer really necessary.)

I get the following results:

---
$ gdc -finline-functions -frelease -O3 -c test1.d
$ gdc -finline-functions -frelease -O3 test.d test1.o
$ ./a.out
0 0 secs 620 ms
1 0 secs 647 ms
4939766238266722816
---

---
$ ldc2 -O3 -release -c test1.d
$ ldc2 -O3 -release test.d test1.o
$ ./test
0 418 ms, 895 μs, and 3 hnsecs
1 409 ms, 776 μs, and 1 hnsec
4939766238266722816
---

---
$ dmd -O -release -inline -c test1.d
$ dmd -O -release -inline test.d test1.o
0 637 ms, 19 μs, and 9 hnsecs
1 722 ms, 57 μs, and 8 hnsecs
4939766238266722816
---

 — David

Reply via email to