2013-07-17 57 views
10

我今天在C#和Java中讀到了post about performance improvement局部變量或類字段?

我仍然停留在這一個:


19.不要過度使用實例變量

性能可以使用局部變量來改善。實例1中的代碼將執行比示例代碼中的2

例1速度快:

public void loop() { 
    int j = 0; 
    for (int i = 0; i<250000;i++){ 
    j = j + 1; 
    } 
} 

例2:

int i; 
public void loop() { 
    int j = 0; 
    for (i = 0; i<250000;i++){ 
    j = j + 1; 
    } 
} 

事實上,我不明白爲什麼它應該更快地實例化一些內存,並在每次調用loop函數完成時釋放它,以便我可以簡單訪問字段。

這是純粹的好奇心,我沒有試圖把變量'i'放在類的範圍內:p 這是真的嗎?使用局部變量更快嗎?或者只是在某種情況下?

+1

我認爲,性能差異可以忽略不計,您應該更加關心開發人員在理解代碼方面的表現。如果你有一個應該是局部變量的字段或屬性,我會在理解它的目的時發生衝突。如果你想知道性能差異,爲什麼不對它進行基準測試(或讀取兩者都生成的IL)? – Matthew

+3

從堆棧訪問變量可能比通過堆引用訪問變量要快。 –

+2

那麼多不好的建議,在那篇文章中,我不知道從哪裏開始 –

回答

9
  1. 堆棧更快然後堆。

    void f() 
    { 
        int x = 123; // <- located in stack 
    } 
    
    int x; // <- located in heap 
    void f() 
    { 
        x = 123 
    } 
    
  2. 別忘了the principle of locality data。本地數據應該更好地緩存在CPU緩存中。如果數據接近,它們將完全加載到CPU緩存中,並且CPU不必從內存中獲取它們。

+0

我覺得你太簡單了。局部變量實際上可以位於堆上,而字段可以位於堆棧上。 – svick

+0

如果你有直接的地址,那麼堆棧或堆沒有區別。 – Andrey

+0

我同意,如果你是指對象和結構與字段的參考 – oakio

1

我懷疑沒有什麼區別,但是在變量是對象成員的情況下,每個訪問都需要通過this(有效)進行間接尋址,而局部變量則不需要。

更一般地說,該對象不需要成員i,它僅用於循環的上下文中,因此在任何情況下使其在本地使用都更好。

5

性能下降到獲得變量所需的步驟數。局部變量地址在編譯時已知(它們是堆棧上已知的偏移量),以便在獲取成員變量的地址之前訪問加載對象'this'的成員以獲取實際對象的地址。

3

即使是這樣,在這種情況下幾乎沒有可測量的差異。 在第一種情況下Probabbly,有一些優化的處理器註冊表層面完成,但再次:

  • 它幾乎無關緊要
  • ,什麼是更重要的,往往難以預測。

在內存方面,它的確是,一樣,沒有任何區別。

第一種情況generaly更好:當你聲明變量有它的imediately使用,這是常用的良好格局,因爲它是

  • 容易理解(責任的範圍)
  • 容易重構
+0

第二個示例在方法未執行時使用更多內存,因爲該變量始終在內存中用於該類的每個實例,無論是否調用「loop」方法。 – Matthew

+0

@Mthethew:在方法中聲明的所有局部變量(在當前執行過程中實際使用或不在)中被分配並按*方式壓入堆棧*。 – Tigran

+0

是的,但是,當'loop'方法退出時,釋放內存,但在示例2中沒有。 – Matthew

0

我測試了一個500,000次迭代的計算,其中我在本地使用了大約20個變量,一個使用了字段。局部變量測試約爲20毫秒,帶有字段的測試約爲30毫秒。當使用局部變量時,性能顯着提高。

性能差異是否相關取決於項目。在您的普通商業應用程序中,性能增益可能不明顯,最好選擇可讀/可維護的代碼,但我正在開發適合這種納米優化的聲音合成軟件。

0

在C#中另一個微小的區別是生成的MSIL指令的數量(我猜它在Java中是相似的)。

這需要兩個指令來加載一個實例字段:

ldarg.0     // load "this" reference onto stack 
ldfld MyClass.myField // find the field and load its value 

...但只需要一個指令加載一個局部變量:

ldloc.0     // load the value at index 0 from the list of local variables