2014-02-07 23 views
1

我也犯了同樣的測試,因爲它是在這個崗位做: new String() vs literal string performanceJava的String =「」與新的String(「」)的性能變化

含義我想考哪一個具有在性能越好。正如我預期的結果是文字的分配速度更快。我不知道爲什麼,但是我做了一些更多任務的測試,並且我發現了一些奇怪的東西:當我讓程序執行超過10.000次的循環時,文字賦值的速度相對不會比低於10.000賦值的速度快。在重複1000,000次時,它甚至比創建新對象要慢。

這裏是我的代碼:

double tx = System.nanoTime(); 
for (int i = 0; i<1; i++){ 
    String s = "test"; 
} 
double ty = System.nanoTime(); 

double ta = System.nanoTime(); 
for (int i = 0; i<1; i++){ 
    String s = new String("test"); 
} 
double tb = System.nanoTime(); 

System.out.println((ty-tx)); 
System.out.println((tb-ta)); 

我讓這個運行像它上面寫的。我剛剛學習Java,老闆讓我做測試,在我提交測試結果後,他問我找到答案,爲什麼會發生這種情況。我找不到任何在谷歌或在計算器上的東西,所以我希望有人能幫助我在這裏。

factor at   1 repetition 3,811565221 
factor at  10 repetitions 4,393570401 
factor at  100 repetitions 5,234779103 
factor at  1,000 repetitions 7,909884116 
factor at 10,000 repetitions 9,395538811 
factor at 100,000 repetitions 2,355514697 
factor at 1,000,000 repetitions 0,734826755 

謝謝!

+3

我強烈懷疑你只是看到熱點隨着時間的推移而更加優化。 「百萬次重複」部分可能顯示了其他一些因素......它真的*不會更快。 –

+1

查找Hotspot並記住垃圾收集,以回答爲什麼你看到與大量執行的區別。對於Java中的未來任務,請儘快忘掉這種優化級別。正如卡亞曼所說 - 擔心這是浪費時間。測量有意義的算法,但不要讓這個結果影響你編寫任何代碼的方式! –

回答

10

首先你必須學習很多關於HotSpot的內幕,特別是你的代碼首先被解釋的事實,然後在編譯成本地代碼的某個點上。

根據代碼的靜態和動態分析結果,編譯時會發生很多優化。

具體來說,在你的代碼,

String s = "test"; 

是明確無操作。編譯器將爲此行發出無碼。剩下的就是循環本身,如果HotSpot證明它沒有可觀察的外部效應,整個循環可能會被消除。

其次,即使代碼

String s = new String("test"); 

可能導致幾乎同樣的事情上面,因爲它是很容易證明你的new String是不能從那裏創建的方法逃避一個實例。

通過您的代碼,測量結果將解釋字節碼的性能,編譯代碼所需的延遲以及通過堆棧替換進行交換所需的時間延遲,以及本機代碼的性能。

基本上,你正在測量的是測量的一切,但你已經着手測量的效果。

爲了使論點更堅實,我已經反覆測試與jmh

@OutputTimeUnit(TimeUnit.NANOSECONDS) 
@BenchmarkMode(Mode.AverageTime) 
@Warmup(iterations = 1, time = 1) 
@Measurement(iterations = 3, time = 1) 
@Threads(1) 
@Fork(2) 
public class Strings 
{ 
    static final int ITERS = 1_000; 
    @GenerateMicroBenchmark 
    public void literal() { 
    for (int i = 0; i < ITERS; i++) { String s = "test"; } 
    } 

    @GenerateMicroBenchmark 
    public void newString() { 
    for (int i = 0; i < ITERS; i++) { String s = new String("test"); } 
    } 
} 

,這些都是結果:

Benchmark  Mode Samples   Mean Mean error Units 
literal  avgt   6  0.625  0.023 ns/op 
newString  avgt   6  43.778  3.283 ns/op 

你可以看到整個法體被淘汰在字符串文字的情況下,雖然new String循環仍然存在,但沒有任何內容,因爲每個循環迭代的時間僅爲0.04納秒。絕對不分配String個實例。

+0

感謝您的快速回復 – user3283766

+0

有一件事需要從這一點中解脫出來,那就是當您不應該在這些測試中浪費您的時間;在過去的十年裏,你不會精通已經被優化成爲性能優化野獸的JVM。你實際進行測試的機會,因此你得到統計數據的謊言已經太大了。 – Gimby

+0

@Gimby:大多數人都同意,但是在某些情況下,您可以做得比單純依靠JVM爲您完成所有工作做得更好。但這種情況非常罕見,需要相當多的知識,分析和時間。而有意義的情況非常罕見。除非你爲了好玩而去做;) – maaartinus