大家在平時開發中大多都會遵循接口編程,這樣就可以方便實現依賴注入也方便實現多態等各種小技巧,但這種是以犧牲性能為代價換取代碼的靈活性,萬物皆有陰陽,看你的應用場景進行取舍。
在項目的性能改造中,發現很多方法簽名的返回值都是采用IEnumerable接口,比如下面這段代碼:
public static void Main(string[] args) { var list = GetHasEmailCustomerIDList(); foreach (var item in list){} Console.ReadLine(); } public static IEnumerable<int> GetHasEmailCustomerIDList() { return Enumerable.Range(1, 5000000).ToArray(); }
這段代碼乍一看也沒啥什么性能問題,foreach迭代天經地義,這個還能怎么優化???
首先我們盡可能把原貌還原出來,簡化后的MSIL如下。
.method public hidebysig static void Main ( string[] args ) cil managed{ IL_0009: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator() IL_000e: stloc.1 .try { IL_000f: br.s IL_001a // loop start (head: IL_001a) IL_0011: ldloc.1 IL_0012: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<int32>::get_Current() IL_0017: stloc.2 IL_0018: nop IL_0019: nop IL_001a: ldloc.1 IL_001b: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() IL_0020: brtrue.s IL_0011 // end loop IL_0022: leave.s IL_002f } // end .try finally { IL_0024: ldloc.1 IL_0025: brfalse.s IL_002e IL_0027: ldloc.1 IL_0028: callvirt instance void [mscorlib]System.IDisposable::Dispose() IL_002d: nop IL_002e: endfinally } // end handler IL_002f: ret} // end of method Program::Main
從IL中看到了標準的get_Current,MoveNext,Dispose 還有一個try,finally,一下子多了這么多方法和關鍵詞,不就是一個簡單的foreach迭代數組嘛?至于搞的這么復雜嘛?這樣在大數據下怎么快的起來?
還有一個奇葩的事,如果你仔細觀察IL代碼,比如這句:[mscorlib]System.Collections.Generic.IEnumerable``1<int32>::GetEnumerator(), 這個GetEnumerator前面是接口IEnumerable,正常情況下應該是具體迭代類吧,按理說應該會調用Array的GetEnumerator方法,如下所示。
[Serializable][ComVisible(true)][__DynamicallyInvokable]public abstract class Array : ICloneable, IList, ICollection, IEnumerable, IStructuralComparable, IStructuralEquatable{ [__DynamicallyInvokable] public IEnumerator GetEnumerator() { int lowerBound = GetLowerBound(0); if (Rank == 1 && lowerBound == 0) { return new SZArrayEnumerator(this); } return new ArrayEnumerator(this, lowerBound, Length); }}
IL中發現的第二個問題我特別好奇,
本文鏈接:http://www.www897cc.com/showinfo-26-12145-0.html面向接口編程,你考慮過性能嗎?
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com