StringBufferにおけるパフォーマンスチューニングの落とし穴
文字列を連結させる場合にStringBufferを使え(最近はStringBuilderか)というのが定石だがじつは落とし穴がある。
下記ソースではいずれも文字列を連結する処理なんだけども、”+”を使用するのが一番速い処理となってしまっている。
ちなみにコンパイラの最適化では1.が3.に置き換えられると思ってた。
※最適化では1.が4.になってた。(Java6で確認)ってことで1.はスレッドセーフではなくなってる。
public static void main(String[] args) { long start = System.currentTimeMillis(); String buf = ""; for (int i = 0; i < 10000; i++) { //1. buf = buf + "aaa" + "bbb"; //2150ms. 2124ms. 2128ms. //2. buf = new StringBuffer(buf) //.append("aaa").append("bbb").toString(); //2155ms. 2144ms. 2150ms. //3. buf = new StringBuffer().append(buf) //.append("aaa").append("bbb").toString(); //4574ms. 4607ms. 4640ms. //4. buf = new StringBuilder(buf) //.append("aaa").append("bbb").toString(); //2130ms. 2194ms. 2180ms. } long end = System.currentTimeMillis(); System.out.println(end - start + "ms."); }
このように書くのが一番速い。(StringBuilderでも誤差1ms.程度)
public static void main(String[] args) { long start = System.currentTimeMillis(); String buf = ""; StringBuffer b = new StringBuffer(buf); for (int i = 0; i < 10000; i++) { b.append("aaa").append("bbb"); //6ms. 4ms. 5ms. } buf = b.toString(); long end = System.currentTimeMillis(); System.out.println(end - start + "ms."); }