2014-01-12 28 views
1

這個問題與記憶和主要表現有關。 最近幾天我反思了這個話題,這不是我需要使用的東西,只是好奇而已。 我創建了一個簡單的例子:創建對象和委派比一個大方法慢得多?

使用沒有授權和不具有內部類

1)的一類:

調用四個內類
public class NoInnerClass { 
public void theMethod(int times){ 
    for(int i=0; i<times; i++){ 
     System.out.println("No Inner hello: " + i); 
    } 
} 
} 

2)的一類。最後一個不一樣NoInnerClass在theMethod方法

public class InnerMain { 
    private Inner1 inner1 = new Inner1(); 

    public void theMethod(int times){ 
     inner1.doIt(times); 
    } 
} 

...

public class Inner4 { 
public void theMethod(int times){ 
    for(int i=0; i<times; i++){ 
     System.out.println("Inner 4 hello: " + i); 
    } 
} 
} 

我測量了這兩種類型的呼叫之間的毫秒的時間差。 差異並不大 - 超過一毫秒。但是如果我們有更復雜的內部對象和更多的委託調用,我們肯定會有更大的差異。

所以問題是:

  • 會在第一時間與這兩種方法之間所使用的內存量差異顯着增加
  • 如果是的話,是有這個(我找不到太多)的任何物品
  • 或者,也許今天的JVM是如此聰明,我們不應該去想它

預先感謝您爲您的回答。

+5

That:「*或者也許今天的JVM非常聰明,我們不應該考慮它*」......這裏明顯的優化是方法內聯,它應該將兩個代碼編譯成基本相同的說明。 。順便說一下,你發現的差異可能是衡量問題,而不是實際的性能差異。 – assylias

+0

修復縮進 –

+0

區別在於多次嘗試的平均次數。並感謝提醒有關內聯代碼:) – user3188414

回答

5

您發現的差異(超過一毫秒)可能很大程度上是您的基準測試技術的人爲因素。而且,在不知道整個運行時間的情況下談論毫秒毫無意義:如果時間在幾百毫秒內,則差異很小;如果時間本身處於單位數毫秒,則差異是顯着的;如果時間以秒爲單位,則差異是測量誤差。

現代JVM優化虛擬調用以達到如此高的效率水平,以至於您看到的任何差異都很難衡量。專注於使用所有可用的編碼技術(包括虛擬呼叫)儘可能使代碼儘可能清晰,並且只有在您的分析器告訴您必要時纔開始優化。

+0

謝謝,我同意你所說的一切。代碼只是一個例子。 但是,如果我們有更大的對象和更多的委託...... – user3188414

+1

@ user3188414對象的大小並不重要。而且,增加對象方法的大小會減少開銷的份額。如果你的程序沒有性能問題,優化它是浪費時間。如果你的程序確實存在性能問題,那幾乎可以保證虛擬調用的開銷不會使前100名列表中的事情減慢你的程序。 – dasblinkenlight

+0

這是我想聽到的答案:)謝謝。 – user3188414

2

絕大多數程序的差異可以忽略不計。是的,方法調用可能需要幾十個cpu週期,但對於大多數方法來說,這遠遠小於調用的方法。在你的情況下,你正在做I/O。即使它只是一個控制檯,重新繪製該控制檯將比調用一個方法昂貴得多。此外,JVM在內聯方法調用方面非常出色,這進一步減少了方法調用開銷(只留下對可重寫方法的類型檢查)。

我建議您不要擔心語言結構的性能,除非您的代碼中存在實際性能問題的證據。

PS:4個方法調用的毫秒數是不合理的。這可能是您的基準測試方法的一個人爲因素。 (定時器的精度如何?您確定基準線程沒有被偷窺到將CPU賦予另一個程序嗎?你是否正在停止垃圾收集?剛剛在編譯器運行?)

哦,和關於內存:差異是堆上的4個對象。當然,這取決於這些對象是什麼(如果每個引用一個巨大的數組,它可能很重要),但小對象需要16個字節的內存。當然你可以節省4 * 16 = 64字節的內存?或者你在詢問堆棧大小的增加嗎?這也是微不足道的。

+0

謝謝大家的意見。 在這個話題中,我想提出這個問題 - 創建對象和方法調用比內聯代碼慢得多。 而且代碼很簡單,我只是作爲一個例子在這裏寫的。最主要的是 - 如果我們在實際應用中有更大的對象和更多的委託,那該怎麼辦...... – user3188414