2011-12-07 70 views
4

例如:
代碼1:調用方法是否會降低性能?

void Main() 
{ 
    Console.WriteLine("Some texts"); 
} 

代碼2:

void Main() 
{ 
    Foo(); 
} 

void Foo() 
{ 
    Console.WriteLine("Some texts"); 
} 

是否代碼2運行比代碼1慢?不過,我覺得當我們構建發佈的JIT將內嵌代碼2這樣的話代碼2將跑步速度最快的代碼1.但是,當我與LinqPad測試他們給我的IL結果:

代碼1:

IL_0000: ldstr  "Some texts" 
IL_0005: call  System.Console.WriteLine 

代碼2:

IL_0000: ldarg.0  
IL_0001: call  UserQuery.Foo 

Foo: 
IL_0000: ldstr  "Some texts" 
IL_0005: call  System.Console.WriteLine 
IL_000A: ret  

正如我們所看到的IL結果代碼2有一些額外步驟調用foo(),這是否證明代碼2的運行速度低於碼1?

+0

您是在Debug還是Release模式下運行? – Tudor

+0

@Tudor:我在[LinqPad](http://www.linqpad.net/)中測試了它們,我不知道它運行的是哪種模式。有沒有辦法讓Visual Studio顯示這樣的IL結果? – JatSing

+9

你有兩匹馬。你想知道哪個更快。你是否(1)在互聯網上向隨機的陌生人詢問哪一個更快,或者(2)彼此競爭,看看哪一個獲勝? –

回答

8

首先,您正在查看IL,而不是JITted彙編代碼。你顯示的東西沒有任何證據。您需要查看JITted輸出以查看JITter是否內嵌了代碼。請注意,JITter從平臺到平臺(例如,x86與x64)以及Framework的版本不同。

其次,當然作爲書面版本二將比版本一運行慢。當我說「按照書面形式」時,我的意思是假設JITter沒有在第二版中插入呼叫。額外的通話增加了幾條機器指令,這些指令當然需要幾個額外的週期來執行(再次,不要忘記我說「寫作!」)。然而,表現的差異極其不可思議。你必須在最嚴格的循環中進行數萬億次和數萬億次的迭代,才能看到有意義的性能差異。

+1

最後,JITer會在第二版中插入呼叫嗎? – JatSing

+3

如果你真的想知道,編譯這兩個版本,通過JITter推他們,看看輸出的組件。 – jason

+1

涉及兩個編譯器。你看到的是C#編譯器的輸出,它產生IL代碼。當你的程序運行時,這個IL代碼將被打亂,這意味着第二個編譯器即時編譯器將爲微處理器生成機器代碼。即使c#編譯器沒有內聯該方法,抖動也可能會發生。 –

1

它很瑣碎(閱讀:有可能),你不應該擔心它。

0

編譯器創建了自己對代碼(彙編代碼)的解釋,因此代碼示例將在CPU中以相同的方式進行處理。 (在發佈模式下)

+0

我假設你是指這裏的JIT編譯器,因爲我相信C#編譯器不會生成彙編代碼。此外,編譯器可能是女性:p – Lukazoid

+0

據我所知,C#編譯器仍然生成彙編代碼。但你可能是正確的編譯器是女性..這就是爲什麼她從來沒有給我警告,她只是後來抱怨:P – stackr

+0

@Lukazoid(和stackr)也許你們兩個正在使用「彙編」在這裏意味着不同的東西。 C#編譯器創建包含IL的程序集。 JIT編譯器創建機器代碼;機器碼有時稱爲「彙編代碼」,因爲它與彙編語言密切相關。 – phoog

1

C#編譯器不會執行內聯操作,這就是您在IL代碼中看到的內容。內聯是JIT優化器的工作,它在運行時執行(如果它決定內聯函數使程序更高效)。

2

是的方法調用減慢了代碼的執行速度,如果它們沒有被c#編譯器或jit編譯器內聯,它會稍微慢一點。但是,除非您的代碼在循環中運行並執行了一百萬次左右,否則您應該專注於生成清晰,易於理解和可維護的代碼。當我開始編程單個語句的執行時間時,單位爲毫秒或微秒。今天,它們以納秒爲單位進行測量。時間通常主要是浪費I/O操作。錯誤的算法也可能被指責一段時間。如果您的設計結構清晰,與一個從一開始就進行了時間優化的代碼相比,更好地替換性能較差的代碼部分要容易得多,因此結構可能很糟糕。

我最近經歷過。我不得不在c#程序中在Visio中生成複雜的圖形。事實證明,Visio自動化非常緩慢。花費了幾分鐘的時間來創建圖形。幸運的是,我已將所有圖形資料放入一個組件中,這些組件通過產品中性界面顯示圖形命令。 I.e .:接口不包含任何Visio特定的東西。用一個新的SVG組件替換我的Visio組件非常容易,它在不到一秒的時間內完成了相同的任務。另外,我的算法或程序的任何其他部分絕對不需要做任何修改。

因爲,我的圖形包裝組件添加更多的方法調用。另外,它通過一個界面進行訪問,這更加緩慢了整個事情。然而,最後,這是這個接口和這些額外的方法調用,這使我可以實現更快的解決方案。記住:分鐘與不到一秒鐘!

2

在這種情況下,通過實施,因爲這是我最後一次閱讀這樣的內容,是的,它會被內聯。

一般來說,答案可能是 - 關於內聯規則的文檔是信息材料,主要是在博客中,而不是規範性文檔。版本之間的細節不僅可以改變,它們幾乎肯定會發生變化。

在實踐中:

如果您懷疑性能熱點可能從手動內聯受益,那就試試吧,再配置文件。或者至少看看那個特定作品的jitter代碼。

從理論上講:

不過,我喜歡知道小方法內聯,都是一樣的。

相關問題