Java で Ruby の Benchmark みたいなことをやる
「大規模サービス技術入門」に影響されてアルゴリズムの勉強をはじめてから実行時間を計ることが多くなったのだけれど、なんか毎回、同じようなコードを書いているので、少し簡単に書けるように工夫してみた。
参考にしたのは Ruby の Benchmark クラス。
Java だとブロックがないので、ラベルの指定方法があまりかっこよくないけど、ちょっと使う分には便利になった。
Block.java
public abstract class Block { public String label; public Block(String label) { this.label = label; } public abstract void yield(); }
Benchmark.java
class Benchmark { private String labelFormat; public Benchmark() { this(8); } public Benchmark(int labelWidth) { this.labelFormat = String.format("%%%ds %%%ds", labelWidth, labelWidth); } public void run(Block... blocks) { List<Times> results = new ArrayList<Benchmark.Times>(); for (Block block : blocks) { long start = System.currentTimeMillis(); block.yield(); long time = System.currentTimeMillis() - start; Times result = new Times(block, time); results.add(result); } System.out.println(String.format(labelFormat, "", "time(ms)")); for (Times result : results) { System.out.println(result); } } class Times { private Block block; private long time; public Times(Block block, long time) { this.block = block; this.time = time; } @Override public String toString() { return String.format(labelFormat, block.label, time); } } }
使用例
404 Blog Not Found:perl - 自動で /a|b|c/ を /[abc]/ にしてくれたら... のベンチマーク が以下のように書ける。
import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; public class RegexBench { public static void main(String[] args) { final Pattern p1 = Pattern.compile("s|t|u|v|w|x|y|z"); final Pattern p2 = Pattern.compile("[stuvwxyz]"); final String alphabes = "abcdefghijklmnopqrstuvwxyz"; final String digits = "01234567890123456789012345"; final int ntimes = 1000000; new Benchmark().run(new Block("alt") { @Override public void yield() { for (int i = 0; i < ntimes; ++i) { p1.matcher(alphabes); } } }, new Block("cclass") { @Override public void yield() { for (int i = 0; i < ntimes; ++i) { p2.matcher(alphabes); } } }); new Benchmark(7).run(new Block("alt") { @Override public void yield() { for (int i = 0; i < ntimes; ++i) { p1.matcher(digits); } } }, new Block("cclass") { @Override public void yield() { for (int i = 0; i < ntimes; ++i) { p2.matcher(digits); } } }); } }