Re: [翻譯] 拆穿 Java StringBuilder 的謠言
本來想說 Java Code Geeks 的文章應該沒啥問題
所以翻完就算了,沒有仔細追究
BUT!
M Jwo 在 blog 上留了一個 comment
坦白說我看不是很懂,全文如下
本文大錯,僅有在 compiler 可以最佳化的有限場景才是,
通常是宣告的地方,不然放到method/loop裡面就知道了,
因為只有在 method/loop 才會對效能造成大影響,
少數幾個 String 根本不再效能需要調教的地方。
其實根本不用那麼麻煩,de-compiler 看一眼就知道
都是改用 StringBuffer/StringBuilder 了。
然後我才真的去翻了原作者提供的 javap 的結果
https://github.com/skuro/stringbuilder/blob/master/java7/CatPlus.class.txt
如果你跟我一樣沒辦法直接看懂 javap
那麼對應原始碼可能比較好懂
public class CatPlus extends ACat {
@Override
protected String cat(String base, String append){
String result = "const1" + base;
result = result + "const2";
return result + append;
}
}
也就是說,根本不是他說的那麼一回事情
在 Oracle JDK 7 之下,其實會用 append() 來代替 + 號
原作者 javap 的結果也是如此
要說效能慢的話,應該是因為他重複 assign 回 result
有 code 為證
我寫了一個單純的 class,在 JDK 6 下測試
public class CatPlus {
public String foo (String a, String b) {
return "const1" + a + "const2" + b;
}
}
javap 之後會得到
public class CatPlus extends java.lang.Object{
public CatPlus();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public java.lang.String foo(java.lang.String, java.lang.String);
Code:
0: new #2; //class java/lang/StringBuilder
3: dup
4: invokespecial #3;
//Method java/lang/StringBuilder."<init>":()V
7: ldc #4; //String const1
9: invokevirtual #5;
//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
12: aload_1
13: invokevirtual #5;
//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
16: ldc #6; //String const2
18: invokevirtual #5;
//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: aload_2
22: invokevirtual #5;
//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
25: invokevirtual #7;
//Method java/lang/StringBuilder.toString:()Ljava/lang/String;
28: areturn
}
所以,至少在 Oracle JDK 6 以後
字串用 + 號作連接跟用 StringBuilder 沒啥差別
========
只能說... 嗯... 愚人節快樂這樣? [核爆]
--
錢鍾書: 說出來的話
http://www.psmonkey.org
比不上不說出來的話
Java 版 cookcomic 版
只影射著說不出來的話
and more......
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 114.25.15.134
推
04/01 23:12, , 1F
04/01 23:12, 1F
→
04/01 23:15, , 2F
04/01 23:15, 2F
推
04/01 23:21, , 3F
04/01 23:21, 3F
→
04/01 23:24, , 4F
04/01 23:24, 4F
→
04/01 23:26, , 5F
04/01 23:26, 5F
→
04/01 23:28, , 6F
04/01 23:28, 6F
→
04/01 23:28, , 7F
04/01 23:28, 7F
→
04/01 23:29, , 8F
04/01 23:29, 8F
本來就不應該用推文的方式來討論
這樣看的人會很痛苦
另外,Java 版從來沒有限制文章字數 or 行數
只在意是否言之有物
請見諒
→
04/01 23:31, , 9F
04/01 23:31, 9F
→
04/01 23:32, , 10F
04/01 23:32, 10F
→
04/01 23:34, , 11F
04/01 23:34, 11F
其實原文也不是那麼悽慘到完全無用
或著說,他給的 CatPlus 的 test case
其實就是要模擬 #1Fc1oO9j 的狀態,也就是
while(FooCondition) {
str += str;
}
在這種情況下,雖然 + 的動作還是會改成用 append()
但是會重複宣告 StringBuilder
這才是真正造成效能瓶頸的地方
+ 號還是會變成 append() 的,這點可以肯定
只能說原 po(包含我)不夠用功,不夠龜毛
外加沾染了國內記者的習性,喜歡標題殺人,如此而已
(謎之聲:還而已咧 [毆殺])
是說,要不是看了這篇
我還真的不知道原本的 + 號惡魔其實已經被處理掉了 XD
※ 編輯: PsMonkey 來自: 114.25.15.134 (04/01 23:46)
推
04/01 23:46, , 12F
04/01 23:46, 12F
→
04/01 23:56, , 13F
04/01 23:56, 13F
推
04/02 01:05, , 14F
04/02 01:05, 14F
討論串 (同標題文章)
以下文章回應了本文:
完整討論串 (本文為第 2 之 8 篇):