2013-02-12 60 views
6

我正在做一些測試,以找出使用getters/setters和直接字段訪問之間的速度差異。我寫了一個簡單的基準測試應用程序是這樣的:爲什麼Method訪問看起來比Field訪問更快?

public class FieldTest { 

    private int value = 0; 

    public void setValue(int value) { 
     this.value = value; 
    } 

    public int getValue() { 
     return this.value; 
    } 

    public static void doTest(int num) { 
     FieldTest f = new FieldTest(); 

     // test direct field access 
     long start1 = System.nanoTime(); 

     for (int i = 0; i < num; i++) { 
      f.value = f.value + 1; 
     } 
     f.value = 0; 

     long diff1 = System.nanoTime() - start1; 

     // test method field access 
     long start2 = System.nanoTime(); 

     for (int i = 0; i < num; i++) { 
      f.setValue(f.getValue() + 1); 
     } 
     f.setValue(0); 

     long diff2 = System.nanoTime() - start2; 

     // print results 
     System.out.printf("Field Access: %d ns\n", diff1); 
     System.out.printf("Method Access: %d ns\n", diff2); 
     System.out.println(); 
    } 

    public static void main(String[] args) throws InterruptedException { 
     int num = 2147483647; 

     // wait for the VM to warm up 
     Thread.sleep(1000); 

     for (int i = 0; i < 10; i++) { 
      doTest(num); 
     } 
    } 

} 

每當我運行它,我得到一致的結果,如這些:http://pastebin.com/hcAtjVCL

我想知道,如果有人可以給我爲什麼現場訪問,似乎要慢一些解釋比getter/setter方法的訪問,以及爲什麼最後8次迭代執行得非常快。


編輯:經考慮assyliasStephen C意見,我已經改變了代碼http://pastebin.com/Vzb8hGdc那裏我得到了略有不同的結果:http://pastebin.com/wxiDdRix

+2

我認爲編譯器內聯了getters。你檢查過字節碼嗎? – jlordo 2013-02-12 11:57:09

+10

'/ *等待VM預熱*/Thread.sleep(1000);' - 這不是它的工作原理。如果JVM沒有做任何事情,它就不會升溫......你的微基準有幾個缺陷。特別是:(i)您並不真正允許JVM進行預熱(ii)您要測試的兩個路徑採用相同的方法,這可能會阻止某些優化。 – assylias 2013-02-12 11:58:53

+11

@jlordo - 內聯由JIT編譯器完成。我將不會在字節碼中看到。 – 2013-02-12 11:59:12

回答

9

解釋是你的基準已經壞了。

第一次迭代是使用解釋器完成的。

Field Access: 1528500478 ns 
Method Access: 1521365905 ns 

第二次迭代由解釋器完成,然後我們翻轉到運行JIT編譯代碼。

Field Access: 1550385619 ns 
Method Access: 47761359 ns 

其餘的迭代都是使用JIT編譯代碼完成的。

Field Access: 68 ns 
Method Access: 33 ns 

etcetera 

的原因,他們難以置信快JIT編譯器已經優化環路走。它發現它們沒有爲計算提供任何有用的東西。 (目前尚不清楚爲什麼第一數目似乎一致地比第二快,但我懷疑優化的代碼測量場與任何有意義的方式方法的訪問。)


的Re 修訂代碼/結果:很明顯,JIT編譯器仍在優化循環。

+0

因此,@Stephen使用訪問器方法不僅有利於封裝,它也有利於速度?聽到這個消息我很高興!!! – Victor 2014-05-29 13:21:36

+0

@Victor - 我不相信你可以得出這個結論。事實上,我不認爲你可以從這個基準測試中得出任何**結論。這是簡單的瑕疵 – 2014-05-29 16:24:51

+0

謝謝斯蒂芬!我明白......我開始這麼想。所以,如果你尋求速度使用直接訪問,如果你看起來更加靈活的設計,使用訪問器的方法? (對不起這個偏題的問題!) – Victor 2014-05-29 16:34:54