程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Effective C#原則31:選擇小而簡單的函數(2)

Effective C#原則31:選擇小而簡單的函數(2)

編輯:關於C語言

因為函數體的每個分支被分解到了獨立的小函數中,而JIT就是 須要這些小函數,這比前面的BuildMsg調用要好。確實,這個例子只是人為的, 而且實際上它也沒什麼太特別的。但想想,你是不是經常寫更“昂貴 ”的例子呢:一個if 語句中是不是每個片段中都包含了20或者更多的語句 呢?你的開銷就是讓JIT在第一次調用它的時候兩個分支都要編譯。如果一個分 支不像是錯誤條件,那到你就招致了本可以簡單避免的浪費。小函數就意味著 JIT編譯器只編譯它要的邏輯,而不是那些沉長的而且又不會立即使用的代碼。 對於很長的switch分支,JIT要花銷成倍的存儲,因此把每個分支的內容定義成 內聯的要比分離成單個函數要好。

JIT編譯器可以更簡單的對小而簡單的 函數進行可登記(enregistration)處理。可登記處理是指進程選擇哪些局部變量 可以被存儲到寄存器中,而這比存儲到堆棧中要好。創建少的局部變量可以能 JIT提供更好的機會把最合適的候選對象放到寄存器中。這個簡單的控制流程同 樣會影響JIT編譯能否如期的進行變量注冊。如果函數只有一個循環,那麼循環 變量就很可能被注冊。然而,當你在一個函數中使用過多的循環時,對於變量注 冊,JIT編譯器就不得不做出一些困難的決擇。簡單就是好,小而簡單的函數很 可能只包含簡單幾個變量,這樣可以讓JIT很容易優化寄存器的使用。

JIT編譯器同樣決定內聯方法。內聯就是說直接使用函數體而不必調用函 數。考慮這個例子:

// readonly name property:
private string _name;
public string Name
{
 get
 {
  return _name;
 }
}
// Access:
string val = Obj.Name;

相對函數的調用開銷來說,屬性訪問器實體包含更少 數的指令:對於函數調用,要先在寄存器中存儲它的狀態,然後從頭到尾執行, 接著存儲返回結果。這還不談如果有參數時,把參數壓到堆棧上還要更多的工作 。如果你這樣寫,這會產生更多的機器指令:

string val = Obj._name;

當然,你應該不會這樣做,因為你已經明白最好不要 創建公共數據成員(參見原則1)。JIT編譯器明白你即須要效率也須要簡潔,所以 它會內聯屬性訪問器。JIT會在以速度或者大小為目標(或者兩個同時要求)時, 內聯一些方法,用函數體來取代函數的調用會讓它更有利。一般情況不用為內聯 定義額外的規則,而且任何已經實現的內聯在將來都可能被改變。另外,內聯函 數並不是你的職責。正好C#語言沒有提供任何關鍵字讓你暗示編譯器說你想內聯 某個函數。實際上,C#編譯器也不支持任何暗示來讓JIT編譯進行內聯。你可以 做的就是確保你的代碼盡可能的清楚,盡可能讓JIT編譯器容易的做出最好的決 定。我的推薦現在就很熟悉了:越小的方法越有可能成為內聯對象。請記住:任 何虛方法或者含有try/catch塊的函數都不可能成為內聯的。

內聯修改了 代碼正要被JIT的原則。再來考慮這個訪問名字屬性的例子:

string val = "Default Name";
if ( Obj != null )
 val = Obj.Name;

JIT編譯器內聯了屬性訪問器, 這必然會在相關的方法被調用時JIT代碼。

你沒有責任來為你的算法決定 最好的機器級別上的表現。C#編譯器以及JIT編譯器一起為你完成了這些。C#編 譯器為每個方法生成IL代碼,而JIT編譯器則把這些IL代碼在目標機器上翻譯成 機器指令。並不用太在意JIT編譯器在各種情況下的確切原則;有這些時間可以 開發出更好的算法。取而代之的,你應該考慮如何以一種好的方式表達你的算法 ,這樣的方式可以讓開發環境的工具以最好的方式工作。幸運的是,這些你所考 慮的這些原則(譯注:JIT工作原則)已經成為優秀的軟件開發實踐。再強調一次 :使用小而簡單的函數。

記住,你的C#代碼經過了兩步才編譯成機器可 執行的指令。C#編譯器生成以程序集形式存在的IL代碼。而JIT編譯器則是在須 要時,以每個函數為單元生成機器指令(當內聯調用時,或者是一組方法)。小函 數可以讓它非常容易被JIT編譯器分期處理。小函數更有可能成為內聯候選對象 。當然並不是足夠小才行:簡單的控制流程也是很重要的。函數內簡單的控制分 支可以讓JIT以容易的寄存變量。這並不是只是寫清晰代碼的事情,也是告訴你 如何創建在運行時更有效的代碼。

返回教程目錄

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved