Re:今までのパフォーマンスコーディングは既に古いかもしれない
via オレンジニュース
これはバイトコードを見れば一目瞭然な訳だが、文字列結合は、"+"を使用したほうが1結合につきバイトコードが2命令減る(後は全く一緒)。元々そうだったのか、Javacが優秀になったのか!?
- 文字列結合にはStringBufferを使いましょう
えーーーーっ,マジですか!?<バイトコードが 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); ・・・
みたいに書いた場合の話かな? それだと POP
と LOAD
が増えるけど,文の数が違うものを直接比較するのは同等じゃないというかちょっとアレな感じ.
ちなみに 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 つの式ですむような連結は今も昔も + 使ってますけどねぇ.