關於結果的討論
之所以使用非同步的StringBuilder是為了提供一個測量性能的基線我也想了解一下各種優化是否真的能夠影響StringBuilder的性能正如我們所看到的StringBuilder的性能可以保持在一個不變的吞吐量水平上因為這些技術的目標在於鎖的優化因此這個結果符合預期在性能測試的另一欄中我們也可以看到使用沒有任何優化的同步的StringBuffer其運行效率比StringBuilder大概要慢三倍
仔細觀察圖的結果我們可以注意到從左到右性能有一定的提高這可以歸功於EliminateLocks不過這些性能的提升比起偏向鎖來說又顯得有些蒼白事實上除了C列以外每次運行時如果開啟偏向鎖最終都會提供大致相同的性能提升但是C列是怎麼回事呢?
在處理最初的數據的過程中我注意到有一項測試在六個測試中要花費格外長的時間由於結果的異常相當明顯因此基准測試似乎在報告兩個完全不同的優化行為經過一番考慮我決定同時展示出高值和低值(B列和C列)由於沒有更深入的研究我只能猜測這裡應用了一種以上的優化(很可能是兩種)並且存在一些競爭條件偏向鎖大多時候會取勝但不非總能取勝如果另一種優化占優了那麼偏向鎖的效果要麼被抑制要麼就被延遲了
這種奇怪的現象是逸出分析導致的明確了這個基准測試的單線程化的本質後我期待著逸出分析會消除鎖從而將StringBuffer的性能提到了與 StringBuilder相同的水平但是很明顯這並沒有發生還有另外一個問題在我的機器上每一次運行的時間片分配都不盡相同更為復雜的是我的幾位同事在他們的機器上運行這些測試得到的結果更混亂了在有些時候這些優化並沒有將程序提速那麼多
前期的結論
盡管圖列出的結果比我所期望的要少但確實可以從中看出各種優化能夠除去鎖產生的大部分開銷但是我的同事在運行這些測試時產生了不同的結果這似乎對測試結果的真實性提出了挑戰這個基准測試真的測量鎖的開銷了麼?我們的結論成熟麼?或者還有沒有其他的情況?在本文的第二部分裡我們將會深入研究這個基准測試力爭回答這些問題在這個過程中我們會發現獲取結果並不困難困難的是判斷出這些結果是否可以回答前面提出的問題
public class LockTest { private static final int MAX = ; // million
public static void main(String[] args) throws InterruptedException { // warm up the method cache
for (int i = ; i < MAX; i++) {
concatBuffer(Josh James Duke);
concatBuilder(Josh James Duke);
}
Systemgc();
Threadsleep();
Systemoutprintln(Starting test);
long start = SystemcurrentTimeMillis();
for (int i = ; i < MAX; i++) {
concatBuffer(Josh James Duke);
}
long bufferCost = SystemcurrentTimeMillis() start;
Systemoutprintln(StringBuffer: + bufferCost + ms);
Systemgc();
Threadsleep();
start = SystemcurrentTimeMillis();
for (int i = ; i < MAX; i++) {
concatBuilder(Josh James Duke);
}
long builderCost = SystemcurrentTimeMillis() start;
Systemoutprintln(StringBuilder: + builderCost + ms);
Systemoutprintln(Thread safety overhead of StringBuffer:
+ ((bufferCost * / (builderCost * )) ) + %\n);
}
public static String concatBuffer(String s String s String s) { StringBuffer sb = new StringBuffer();
sbappend(s);
sbappend(s);
sbappend(s);
return sbtoString();
}
public static String concatBuilder(String s String s String s) {
StringBuilder sb = new StringBuilder(); sbappend(s); sbappend(s); sbappend(s); return sbtoString();
}
}
[] [] [] []
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27669.html