tokuhirom's Blog

nanobench - Java 8 で簡単にマイクロベンチマークをとれるフレームワーク作った

Caliper や JMH などを試してみたが、案外あれは使うのが難しかったり、インストールが難しかったり、結果がよみづらかったりする。 Perl 5 に標準添付されているベンチマークフレームワークであるところの Benchmark.pm と同じぐらい気軽な感じで使えるベンチマークフレームワークが Java 8 用にあれば便利なのではないか、と思ったので作ってみた。

https://github.com/tokuhirom/nanobench

先日つくった HTML escape に関するマイクロベンチマークを nanobench を使って書きなおしてみる。


package me.geso.microbenchmarks;

import me.geso.nanobench.Benchmark;

import org.apache.commons.lang3.StringEscapeUtils;
import org.junit.Test;
import org.springframework.web.util.HtmlUtils;

import com.google.common.html.HtmlEscapers;

public class HTMLEscapeTest {
    @Test
    public void testHTMLEscape() throws Exception {
        final String src = "<><><><>&&&&;;;;jl2kjlnnfljflksdjfuowu-9urjnl321knl;fu3poifuokbkvnl;uigufjslfjadsipuru1o2krn;lkmfzkjhvojopijkJ:LJKU)!*)($J!KLJOIFHS)JPJ";

        new Benchmark()
                .add("guava", () -> {
                    HtmlEscapers.htmlEscaper().escape(src);
                })
                .add("commons", () -> {
                    StringEscapeUtils.escapeHtml4(src);
                })
                .add("String.replace",
                        () -> {
                            src.replace("&", "&amp;").replace(">", "&gt;")
                                    .replace("<", "&lt;")
                                    .replace("'", "&apos;")
                                    .replaceAll("\"", "&quot;");
                        }).add("Spring", () -> {
                    HtmlUtils.htmlEscape(src);
                }).runByTime(1).timethese().cmpthese();
    }
}

Score:

guava:  1 wallclock secs ( 1.14 usr +  0.06 sys =  1.20 CPU) @ 972828.08/s (n=1168278)
commons:  1 wallclock secs ( 1.07 usr +  0.00 sys =  1.08 CPU) @ 39361.53/s (n=42403)
String.replace:  1 wallclock secs ( 1.07 usr +  0.01 sys =  1.08 CPU) @ 61647.92/s (n=66395)
Spring:  1 wallclock secs ( 1.02 usr +  0.00 sys =  1.03 CPU) @ 878340.23/s (n=901452)

Comparison chart:

                      Rate  guava  commons  String.replace  Spring
           guava  972828/s     --    2372%           1478%     11%
         commons   39362/s   -96%       --            -36%    -96%
  String.replace   61648/s   -94%      57%              --    -93%
          Spring  878340/s   -10%    2131%           1325%      --

出力がとても見やすいので、どれが速いのか一目瞭然である。

コードは、Java 8 の lambda 式を利用することにより、annotation を利用した場合よりもさらに簡単に書けるようになっている。

Benchmark.java 自体が1ファイルなので、そのままコピペしてプロジェクトに突っ込んでつかうこともできる。