2009-08-19 51 views
5

背景我可以比較IL代碼以確定哪種技術更快或更好?

This question讓我思考一些事情。最近,由於我一直在尋找linq pad的IL功能,我一直在比較兩種方法的IL代碼來解決同一個問題,以「確定」哪一個最好。

使用鏈接到上面的問題,有關轉換數組,我產生用於兩個答案IL代碼:

var arr = new string[] { "1", "2", "3", "4" }; 
var result = Array.ConvertAll(arr, s => Int32.Parse(s)); 

製備:

IL_0001: ldc.i4.4  
IL_0002: newarr  System.String 
IL_0007: stloc.2  
IL_0008: ldloc.2  
IL_0009: ldc.i4.0  
IL_000A: ldstr  "1" 
IL_000F: stelem.ref 
IL_0010: ldloc.2  
IL_0011: ldc.i4.1  
IL_0012: ldstr  "2" 
IL_0017: stelem.ref 
IL_0018: ldloc.2  
IL_0019: ldc.i4.2  
IL_001A: ldstr  "3" 
IL_001F: stelem.ref 
IL_0020: ldloc.2  
IL_0021: ldc.i4.3  
IL_0022: ldstr  "4" 
IL_0027: stelem.ref 
IL_0028: ldloc.2  
IL_0029: stloc.0  
IL_002A: ldloc.0  
IL_002B: ldsfld  UserQuery.CS$<>9__CachedAnonymousMethodDelegate1 
IL_0030: brtrue.s IL_0045 
IL_0032: ldnull  
IL_0033: ldftn  b__0 
IL_0039: newobj  System.Converter<System.String,System.Int32>..ctor 
IL_003E: stsfld  UserQuery.CS$<>9__CachedAnonymousMethodDelegate1 
IL_0043: br.s  IL_0045 
IL_0045: ldsfld  UserQuery.CS$<>9__CachedAnonymousMethodDelegate1 
IL_004A: call  System.Array.ConvertAll 
IL_004F: stloc.1  

b__0: 
IL_0000: ldarg.0  
IL_0001: call  System.Int32.Parse 
IL_0006: stloc.0  
IL_0007: br.s  IL_0009 
IL_0009: ldloc.0  
IL_000A: ret   

和對方的回答:

var arr = new string[] { "1", "2", "3", "4" }; 
var result = arr.Select(s => int.Parse(s)).ToArray(); 

產生:

在此
IL_0001: ldc.i4.4  
IL_0002: newarr  System.String 
IL_0007: stloc.2  
IL_0008: ldloc.2  
IL_0009: ldc.i4.0  
IL_000A: ldstr  "1" 
IL_000F: stelem.ref 
IL_0010: ldloc.2  
IL_0011: ldc.i4.1  
IL_0012: ldstr  "2" 
IL_0017: stelem.ref 
IL_0018: ldloc.2  
IL_0019: ldc.i4.2  
IL_001A: ldstr  "3" 
IL_001F: stelem.ref 
IL_0020: ldloc.2  
IL_0021: ldc.i4.3  
IL_0022: ldstr  "4" 
IL_0027: stelem.ref 
IL_0028: ldloc.2  
IL_0029: stloc.0  
IL_002A: ldloc.0  
IL_002B: ldsfld  UserQuery.CS$<>9__CachedAnonymousMethodDelegate1 
IL_0030: brtrue.s IL_0045 
IL_0032: ldnull  
IL_0033: ldftn  b__0 
IL_0039: newobj  System.Func<System.String,System.Int32>..ctor 
IL_003E: stsfld  UserQuery.CS$<>9__CachedAnonymousMethodDelegate1 
IL_0043: br.s  IL_0045 
IL_0045: ldsfld  UserQuery.CS$<>9__CachedAnonymousMethodDelegate1 
IL_004A: call  System.Linq.Enumerable.Select 
IL_004F: call  System.Linq.Enumerable.ToArray 
IL_0054: stloc.1  

b__0: 
IL_0000: ldarg.0  
IL_0001: call  System.Int32.Parse 
IL_0006: stloc.0  
IL_0007: br.s  IL_0009 
IL_0009: ldloc.0  
IL_000A: ret  

來看,我可以告訴的是,後一種選擇

  • 花費1個額外的行
  • 使用LINQ時,第一答案不
  • 創建詮釋的不同通過IL_0039。

問題

  • 對於這個具體的例子,是我的假設是否正確?
  • 一般來說,我應該如何通過IL代碼比較兩種解決方案?
  • 一般來說,IL LOC較少的解決方案意味着它會更快還是使用更少的內存?
  • 正如標題所說,我可以比較IL代碼以確定哪種技術更快或更好?

FWIW,我不經常這樣做,只是在工作中的開發人員之間發生一些討論時偶爾出現一次。有人會說「哦,這是更有效率」,我們會把它扔到linqpad來檢查IL代碼。此外,FWIW,我幾乎總是遵循得到它的工作之前,得到它的高效率/快速的方法。正是這樣的人不認爲我不斷比較的IL代碼是什麼我開發:)

+0

嗨,艾倫,非常感謝你! – abatishchev 2009-08-19 11:21:02

回答

8
  • 對於這個具體的例子,是我的假設是否正確?
  • 一般來說,我應該如何通過IL代碼比較兩種解決方案?
  • 一般來說,IL LOC較少的解決方案意味着它會更快還是使用更少的內存?
  • 正如標題所說,我可以比較IL代碼以確定哪種技術更快或更好?

1)您的假設對於發生的事情是正確的。

2)你需要了解什麼IL代碼,以確定哪些是「更好」

3)號這意味着需要較少的指令來運行做。但是,這些單獨的指令可能會使用更多內存或更少。例如,您所引用的指令在一種情況下是創建一個Func委託,另一個是創建一個Converter對象。沒有更多的信息,很難分辨哪兩件東西更貴。

4)是的,沒有....

的問題是,IL代碼會告訴你發生了什麼,但它確實在IL嵌套調用,都將是大的性能驅動程序。如果IL代碼在任何地方都進行簡單的操作,通常越短越好(雖然單個IL操作本身可以在速度上變化)。當代碼調用其他類型的方法或構造函數時,例如你的代碼,這無法單獨從這個角度來說明。在一種情況下,一行IL可能需要更長的時間(例如,如果它調用的是昂貴的方法),則在另一種情況下(它們在執行簡單操作的情況下)會比50更長。

例如,在上面的例子中,前20個操作非常非常快,最後幾個操作幾乎佔用了所有可執行時間。

+0

有趣的是,我認爲它會顯示所有嵌套的IL調用,謝謝你的偉大答案!作爲一個側面問題,你是否知道我可以在哪裏瞭解更多關於IL的知識,或者我是否應該關心它?對不起,我知道那些是涉及到的問題 – 2009-08-19 00:59:32

+2

爲了真正理解IL,開始閱讀編譯器理論和/或彙編語言。它有助於瞭解它在做什麼。否則,MSDN的Reflection.Emit部分有很多很好的信息。 – 2009-08-19 01:07:21

3

這兩個答案的工作塊在IL 004A(和IL 004F爲第二個)完成。除非您知道這些外部電話的費用,否則您無法比較兩種答案的表現。

相關問題