これは何
java9(earlyAccess版)で文字列の結合を実験したもの
※9 Build 134
テスト機のスペック
- Windows10
- Core i7
- メモリは8GB
実験に使ったソース
JMHで実行した結果
- java8
Benchmark Mode Cnt Score Error Units
jmhTest.MyBenchmarkStringLine.call1StringLine thrpt 10 116.587 ± 0.733 ops/s
jmhTest.MyBenchmarkStringLine.call2StringConcat thrpt 10 69.140 ± 2.958 ops/s
jmhTest.MyBenchmarkStringLine.call3StringBuffer thrpt 10 105.525 ± 1.598 ops/s
jmhTest.MyBenchmarkStringLine.call4StringBuilder thrpt 10 103.146 ± 4.292 ops/s
- java9
Benchmark Mode Cnt Score Error Units
jmhTest.MyBenchmarkStringLine.call1StringLine thrpt 10 262.700 ± 4.913 ops/s
jmhTest.MyBenchmarkStringLine.call2StringConcat thrpt 10 136.718 ± 0.869 ops/s
jmhTest.MyBenchmarkStringLine.call3StringBuffer thrpt 10 52.900 ± 0.437 ops/s
jmhTest.MyBenchmarkStringLine.call4StringBuilder thrpt 10 56.853 ± 0.736 ops/s
javapの結果
-
java8
https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/MyBenchmarkStringLine_java8.txt -
java9
https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/MyBenchmarkStringLine_java9.txt
http://www.slideshare.net/bitter_fox/10java9java8 に載っている通り、java9だとinvokedynamic が使われていることが確認できる。
まとめ ※java9はまだ正式版ではないので、正式版リリース後に改めて確認が必要!
- java8だと、Stringを+でつなげたものとBuilder、Bufferで差異がそんなにないが、java9は+で繋げたものが速い。
- java9はconcatで繋げたときも、Builderより速い…本当に?
きつねさんにTwitterで教えていただいた。
@deaf_tadashi ありがとうございます.非常に面白い結果でびっくりしました.実際indy化ではあまり性能向上はそこまで無いと思っていたので.indy化の影響とは別にCompact Stringの影響も含まれているのかなと思いました.
— ミスティックきつね (@bitter_fox) 2016年9月4日
@deaf_tadashi Compact Stringは今までcharの配列で保存していたのをbyteの配列で保存するように使用というものです.また,英数字などのみの場合はUTF-16ではなくLatin-1という文字コードで保持するようになりました
— ミスティックきつね (@bitter_fox) 2016年9月4日
@deaf_tadashi これによって省メモリ化がされて,配列のコピーもその分高速になるのですが,ベンチマークでは数字でLatin-1に収まる物しか扱っていないので,String.+とString.concatがかなり高速になったのではないかと思います.
— ミスティックきつね (@bitter_fox) 2016年9月4日
@deaf_tadashi ぜひとも,日本語などのLatin-1に収まらない文字でベンチマークを取ると,違った結果になるかもしれないので,試してみていただけると嬉しいです.
— ミスティックきつね (@bitter_fox) 2016年9月4日
文字列は色々な最適化が1つのバージョン内に入っているので,具体的にどれが影響したかは言い難いですがw
追加テストを実施
実験用コード
半角英字のみ
全角文字のみ
実験結果
半角英字のみ
- Java8
Benchmark Mode Cnt Score Error Units
jmhTest.MyBenchmarkStringLineHankaku.call1StringLine thrpt 10 140.927 ± 1.069 ops/s
jmhTest.MyBenchmarkStringLineHankaku.call2StringConcat thrpt 10 35.711 ± 0.432 ops/s
jmhTest.MyBenchmarkStringLineHankaku.call3StringBuffer thrpt 10 96.962 ± 0.493 ops/s
jmhTest.MyBenchmarkStringLineHankaku.call4StringBuilder thrpt 10 99.713 ± 1.548 ops/s
- Java9
Benchmark Mode Cnt Score Error Units
jmhTest.MyBenchmarkStringLineHankaku.call1StringLine thrpt 10 90.187 ± 2.961 ops/s
jmhTest.MyBenchmarkStringLineHankaku.call2StringConcat thrpt 10 46.822 ± 3.277 ops/s
jmhTest.MyBenchmarkStringLineHankaku.call3StringBuffer thrpt 10 68.937 ± 2.796 ops/s
jmhTest.MyBenchmarkStringLineHankaku.call4StringBuilder thrpt 10 78.742 ± 2.665 ops/s
全角文字のみ
- Java8
Benchmark Mode Cnt Score Error Units
jmhTest.MyBenchmarkStringLineZenkaku.call1StringLine thrpt 10 141.394 ± 0.301 ops/s
jmhTest.MyBenchmarkStringLineZenkaku.call2StringConcat thrpt 10 36.051 ± 0.287 ops/s
jmhTest.MyBenchmarkStringLineZenkaku.call3StringBuffer thrpt 10 98.531 ± 0.644 ops/s
jmhTest.MyBenchmarkStringLineZenkaku.call4StringBuilder thrpt 10 98.985 ± 3.572 ops/s
- Java9
Benchmark Mode Cnt Score Error Units
jmhTest.MyBenchmarkStringLineZenkaku.call1StringLine thrpt 10 92.686 ± 0.299 ops/s
jmhTest.MyBenchmarkStringLineZenkaku.call2StringConcat thrpt 10 49.554 ± 0.684 ops/s
jmhTest.MyBenchmarkStringLineZenkaku.call3StringBuffer thrpt 10 56.950 ± 6.474 ops/s
jmhTest.MyBenchmarkStringLineZenkaku.call4StringBuilder thrpt 10 69.917 ± 0.210 ops/s
追加テストをふまえたまとめ(再)
- 数値でない場合の結合速度は爆速になるどころか、遅くなっている。
- Java9はまだ開発途上ということもあってか、StringBuilderの処理速度も落ちているのが気になるところ。正式版リリースまでにはJava8同等の処理速度に戻るのであろうか?
- Javaのバージョンによって文字列の最適化だったり、内部処理の最適化だったりで文字列の操作が高速、なコーディング方法は異なってくる。
何でもかんでもStringBuilderを使えや、と言ってくる先輩エンジニアの言うことは無視して、疑問に思ったら自分で性能を確認しよう。 - このテストコードを書いた翌日に38度の熱を出したのはきっと知恵熱に違いない。