Re:今までのパフォーマンスコーディングは既に古いかもしれない

via オレンジニュース

  • 文字列結合にはStringBufferを使いましょう
これはバイトコードを見れば一目瞭然な訳だが、文字列結合は、"+"を使用したほうが1結合につきバイトコードが2命令減る(後は全く一緒)。元々そうだったのか、Javacが優秀になったのか!?

えーーーーっ,マジですか!?<バイトコードが 2 命令減る
そんなわけで (どんなわけで?),しょーもないクラスで確認.

public class Text {
    public String plus(String s, String t) {
        return s + t;
    }
    public String append(String s, String t) {
        return new StringBuffer(s).append(t).toString();
    }
}

こいつをコンパイルして javap してみたところ...

Compiled from "Text.java"
public class aop.Text extends java.lang.Object{
public aop.Text();
  Code:
   0:   aload_0
   1:   invokespecial   #9; //Method java/lang/Object."<init>":()V
   4:   return

public java.lang.String plus(java.lang.String,java.lang.String);
  Code:
   0:   new     #17; //class StringBuffer
   3:   dup
   4:   aload_1
   5:   invokestatic    #23; //Method java/lang/String.valueOf:(Ljava/lang/Objec
t;)Ljava/lang/String;
   8:   invokespecial   #26; //Method java/lang/StringBuffer."<init>":(Ljava/lan
g/String;)V
   11:  aload_2
   12:  invokevirtual   #30; //Method java/lang/StringBuffer.append:(Ljava/lang/
String;)Ljava/lang/StringBuffer;
   15:  invokevirtual   #34; //Method java/lang/StringBuffer.toString:()Ljava/la
ng/String;
   18:  areturn

public java.lang.String append(java.lang.String,java.lang.String);
  Code:
   0:   new     #17; //class StringBuffer
   3:   dup
   4:   aload_1
   5:   invokespecial   #26; //Method java/lang/StringBuffer."<init>":(Ljava/lan
g/String;)V
   8:   aload_2
   9:   invokevirtual   #30; //Method java/lang/StringBuffer.append:(Ljava/lang/
String;)Ljava/lang/StringBuffer;
   12:  invokevirtual   #34; //Method java/lang/StringBuffer.toString:()Ljava/la
ng/String;
   15:  areturn

}

んー,StringBuffer を使っても "+" につきバイトコードが 2 命令増えてるようには見えませんが... ????
もしかしてもしかすると,

    StringBuffer buf = new StringBuffer(s);
    buf.append(t);
    ・・・

みたいに書いた場合の話かな? それだと POPLOAD が増えるけど,文の数が違うものを直接比較するのは同等じゃないというかちょっとアレな感じ.
ちなみに String に働く "+" 演算子の振る舞いは Java 言語仕様で決まっていて,昔からこんなもんだったと思います.上でやったような比較では大昔から差はなかったはず.Tiger になって StringBuffer ではなく StringBuilder が使われるようになるからその意味では古い話題といえるかもしれませんが.
よくパフォチューで StringBuffer を使えといわれるのは,"+" というより "+=" との比較ではないかと.

    String s = "hoge";
    for (int i = 0; i < 3; ++i) {
        s += i;
    }

みたいなことをすると,

    String s = "hoge";
    for (int i = 0; i < 3; ++i) {
        s = new StringBuffer(s).append(i).toString();
    }

と同等になってしまい,繰り返しの度に StringBufferインスタンス化&文字列化するのでひどく効率が悪いよねっていう話.
"+" が効率悪いという話は自分は知らなかったけどなぁ.っていうか,1 つの式ですむような連結は今も昔も + 使ってますけどねぇ.