今までのパフォーマンスコーディングは既に古いかもしれない(続・補足)

  • StringBuffer

http://d.hatena.ne.jp/yasuff11/20050126#p1
周りから聞いて初めてオレンジニュースに載ってるのを知りました。ビックリした(^_^;)
先月書いた内容では、コードも何も無くて突っ込まれて当然でした。あの時はある神の言葉が「文字列結合は"+"じゃなくて"StringBuffer"でやりなさい!」と啓示されたことがきっかけで"+"なんでダメなの?って感じで書きました。
実際のテストコードは、以下の通り。(ですが、tempでやってたため残ってなかったので再度書き直してみる)


private static final String FIXED_STRING = "テスト文字1";
// 1."+"演算子による文字列結合
public String runStringPlus(String str) {
return FIXED_STRING + str;
}

// 2.StringBufferによる文字列結合
public String runStringBuffer(String str) {
StringBuffer sb = new StringBuffer();
sb.append(FIXED_STRING);
sb.append(str);
return sb.toString();
}

そして、このテストコードから出力されるjavapは、以下の通り。

public java.lang.String runStringPlus(java.lang.String);
Code:
0: new #7; //class StringBuffer
3: dup
4: invokespecial #8; //Method java/lang/StringBuffer."":()V
7: ldc #9; //String テスト文字1
9: invokevirtual #10; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
12: aload_1
13: invokevirtual #10; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
16: invokevirtual #11; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
19: areturn

public java.lang.String runStringBuffer(java.lang.String);
Code:
0: new #7; //class StringBuffer
3: dup
4: invokespecial #8; //Method java/lang/StringBuffer."":()V
7: astore_2
8: aload_2
9: ldc #9; //String テスト文字1
11: invokevirtual #10; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
14: pop
15: aload_2
16: aload_1
17: invokevirtual #10; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
20: pop
21: aload_2
22: invokevirtual #11; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
25: areturn

前回書いた時よりたくさんjavapに違いが・・・。この原因は、そう記述の仕方なのです。
id:koichikさんに突っ込まれてますが、確かに文の数が違うものと比べても・・・なんですが、"+"だと上記の1の様に記述するのに、"StringBuffer"ではきっと上記の2の様なコードになると思われます。いやいや、new StringBuffer().append(FIXED_STRING).append(str).toString() と記述するカモしれません。StringBufferで記述すると同じ行になる人もいれば多くなる人もいるということなのです。
murayamaさんからコメント頂けたように、「あらゆる場合に」StringBufferを使うべきだといつからか覚えていたために、本来の前提条件を知らず"+"ではなくStringBufferで書き直してきた人も多いんじゃないかしら?私はその一人でした orz
参考URL via id:koichikさん
http://d.hatena.ne.jp/koichik/20050207#1107794429

  • フィールド変数で直接計算せずにローカル変数で計算してから代入した方が速いって習ったのに(誰に?)

あれからまた古いテクニック@1.3は死んでました。以下がサンプルコード。


private static final int inCount = 100;
private int classVal;
private static int staticVal;
public void incClassVal() {
for(int i = 0; i < inCount; i++) {
classVal = classVal + 1;
}
}

public void incStaticVal() {
for(int i = 0; i < inCount; i++) {
staticVal = staticVal + 1;
}
}

public void incLocalVal1() {
int val = 0;
for(int i = 0; i < inCount; i++) {
val = val + 1;
}
classVal = val;
}

public void incLocalVal2() {
int val = 0;
for(int i = 0; i < inCount; i++) {
val = val + 1;
}
staticVal = val;
}

そして結果。

JDK1.4.2_02
クラス変数 :5248(ms)
static変数 :6680(ms)
ローカル→クラス変数 :6902(ms)
ローカル→static変数 :6809(ms)

JDK1.3.1_02
クラス変数 :7835(ms)
static変数 :6289(ms)
ローカル→クラス変数 :3125(ms)
ローカル→static変数 :2473(ms)

やっぱりJDK1.3で使用できた小手先テクニックが死んでる orz...