ベンチマークなモジュール
D言語で気軽に時間測定がしたい
昔書いたコードを引っ張りだしてきた.
// Written in the D programming language /** * This module provides a simple benchmark utility. * * Author: $(WEB profile.livedoor.com/repeatedly/, tama) */ module benchmark; import core.memory : GC; import std.cstream : dout; import std.perf : PerformanceCounter; import std.string : ljustify; /** * Benchmarks D codes based on Ruby's benchmark module. * * Example: ----- enum Limit = 1000_000_000; benchmark!((x) { x.item("for", { for (int i; i < Limit; i++) { } }); x.item("while", { int i; while (i < Limit) i++; }); x.item("foreach", { foreach (i; 0..Limit) { } }); }); ----- * Result on my machine(Windows XP, Athlon 64 X2 4400+) * * Benchmark! * for : 3.691605s * while : 3.151104s * foreach : 3.152668s */ class Benchmark { private: /** * Represents a benchmark item */ static struct Item { string caption; Action action; } alias void delegate() Action; uint width; // caption width Item[] items; PerformanceCounter timer; public: this() { timer = new PerformanceCounter; } /** * Registers a benchmark item. * * Params: * caption = display caption. * action = execute action. */ void item(string caption, Action action) in { assert(action); } body { if (width < caption.length) width = caption.length + 1; items ~= Item(caption, action); } alias item report; /** * Measures benchmark collection. * Display unit is seconds. */ void measure() { measure(width); } /** * 'measure' of $(D_PARAM width) set version. * * Params: * width = user set width. */ void measure(uint width) { foreach (item; items) { GC.collect; timer.start; item.action(); timer.stop; dout.writefln(item.caption.ljustify(width) ~ ": %fs", cast(real)timer.microseconds / cast(real)1000_000); } } alias measure exec, run; /** * Iterates through the benchmark collection. */ int opApply(int delegate(ref Item) dg) { int result; for (uint i; i <= items.length; i++) { result = dg(items[i]); if (result) break; } return result; } } /** * Executes benchmark in makeup. * * Params: * rehearsal = duplicates an benchmark if true. */ void benchmark(alias func)(bool rehearsal = false) { auto benchmark = new Benchmark; func(benchmark); if (rehearsal) { dout.writefln("Rehearsal!"); benchmark.measure; dout.writefln(""); dout.flush; } dout.writefln("Benchmark!"); benchmark.measure; dout.flush; } unittest { enum Limit = 1000_000_0; benchmark!((x) { x.item("for", { for (int i; i < Limit; i++) { } }); x.item("while", { int i; while (i < Limit) i++; }); x.item("foreach", { foreach (i; 0..Limit) { } }); })(true); }
std.stdio.Fileとかが出来る前だからste.cstreamとか使ってるというね.今だと黒歴史なdoutじゃなくてstdoutだなぁ.