diff --git a/source/app.d b/source/app.d index 0d402c1..b2ef27b 100644 --- a/source/app.d +++ b/source/app.d @@ -1,12 +1,13 @@ -import util : make, rcarray, StdArray, StdxArray, EMSIArray; +import util; import std.stdio : stderr, writeln; import std.datetime : Duration; import std.meta : AliasSeq; -alias tests = AliasSeq!(testInsert, testInsertDelete, testConcat); -alias containers = AliasSeq!(int[], StdArray!int, EMSIArray!int, rcarray!int, StdxArray!int); +alias tests = AliasSeq!(testInsert, testDelete, testConcat); +alias setupFuns = AliasSeq!(noSetup, makeAndInsert, makeAndInsert); +alias containers = AliasSeq!(int[], StdArray!int, rcarray!int, EMSIArray!int, StdxArray!int); enum times = 100000; void testInsert(Container, size_t size = 100)() @@ -15,7 +16,7 @@ void testInsert(Container, size_t size = 100)() //debug stderr.writeln("Testing inserts on ", typeof(container).stringof); - foreach (i; 0 .. size) + static foreach (i; 0 .. size) { container ~= 42; } @@ -23,17 +24,10 @@ void testInsert(Container, size_t size = 100)() assert(container.length == size && container[size - 1] == 42); } -void testInsertDelete(Container, size_t size = 100)() +void testDelete(Container, size_t size = 100)(ref Container container) { - auto container = make!Container(); - //debug stderr.writeln("Testing inserts+deletes on ", typeof(container).stringof); - foreach (i; 0 .. size) - { - container ~= 42; - } - foreach (i; 0 .. size) { static if (is(Container : StdxArray!U, U)) @@ -53,20 +47,11 @@ void testInsertDelete(Container, size_t size = 100)() assert(container.length == 0); } -void testConcat(Container, size_t size = 100)() +void testConcat(Container, size_t size = 100)(ref Container container) { - auto a = make!Container(); - auto b = make!Container(); + auto c = container ~ container; - foreach (i; 0 .. size / 2) - { - a ~= 1; - b ~= 2; - } - - auto c = a ~ b; - - assert(c.length == size); + assert(c.length == size * 2); } auto testContainers(Containers...)() @@ -77,10 +62,12 @@ auto testContainers(Containers...)() Duration[][string] results; - static foreach (test; tests) - { - results[test.stringof] = benchmark!(staticMap!(test, Containers))(times).array; - } + static foreach (i, test; tests) + {{ + alias ts = staticMap!(test, Containers); + alias ss = staticMap!(setupFuns[i], Containers); + results[test.stringof] = benchmarkWithSetup!(Transpose!(2, ts, ss))(times).array; + }} return results; } @@ -104,14 +91,16 @@ void plotResults(Containers...)(Duration[][string] results) import plt = matplotlibd.pyplot; auto i = 0; - foreach (test, testResults; results) + foreach (test; tests) { + auto testResults = results[test.stringof]; + import std.range : iota; import std.algorithm : map; import std.array : array; import std.conv : to; - auto title = test ~ " (" ~ times.to!string ~ " runs)"; + auto title = test.stringof ~ " (" ~ times.to!string ~ "x)"; auto x = iota(testResults.length); auto height = testResults.map!(d => d.total!"msecs").array; @@ -121,18 +110,23 @@ void plotResults(Containers...)(Duration[][string] results) names ~= Container.stringof; } - plt.subplot(results.length, 1, ++i); + i++; + //plt.subplot(results.length, 1, i); + plt.clf(); plt.bar(x, height); plt.xticks(x, names); plt.ylabel("Time (ms)"); + plt.ylim(0, 3000); plt.title(title); + plt.savefig("out/" ~ i.to!string ~ ".png", ["dpi": 500]); } - plt.show(); + //plt.show(); } void main() { auto results = testContainers!containers; + results.printResults!containers; results.plotResults!containers; } diff --git a/source/util.d b/source/util.d index 6e60a56..08da756 100644 --- a/source/util.d +++ b/source/util.d @@ -29,3 +29,82 @@ T make(T : StdxArray!U, U)() { return T(); } + +T makeAndInsert(T, size_t size = 100)() +{ + T t = make!T(); + + static foreach (i; 0 .. size) + { + t ~= 42; + } + + return t; +} + +T[2] makeAndInsert2(T, size_t totalSize = 100)() +{ + T a = make!T(); + T b = make!T(); + + static foreach (i; 0 .. totalSize / 2) + { + a ~= 1; + b ~= 2; + } + + return [a, b]; +} + +import core.time : Duration; +import std.datetime.stopwatch : StopWatch, AutoStart; +Duration[funs.length / 2] benchmarkWithSetup(funs...)(uint n) +{ + Duration[funs.length / 2] result; + + auto sw = StopWatch(AutoStart.no); + + static foreach (i; 0 .. funs.length / 2) + {{ + alias fun = funs[i * 2]; + alias setup = funs[i * 2 + 1]; + + sw.reset(); + foreach (_; 0 .. n) + { + static if (is(typeof(setup()) == void)) + { + sw.start(); + fun(); + } + else + { + auto setupResult = setup(); + sw.start(); + fun(setupResult); + } + + sw.stop(); + } + result[i] = sw.peek(); + }} + + return result; +} + +template Transpose(size_t N, alias A, Args...) +{ + import std.meta : AliasSeq; + static assert(N == 2); + + static if (Args.length == 1) + { + alias Transpose = AliasSeq!(A, Args[0]); + } + else + { + alias Transpose = AliasSeq!(A, Args[(Args.length - 1) / 2], Transpose!(N, Args[0], Args[1 .. (Args.length - 1) / 2], Args[(Args.length - 1) / 2 + 1 .. $])); + } +} + +void noSetup(T)() {}