接上篇繼續(xù),本文的完整源代碼也在上篇文章中。 枚舉數(shù)組和普通枚舉性能差異有些人可能知道,.net在處理枚舉時(shí),對(duì)于數(shù)組有特別的優(yōu)化,所以,當(dāng)枚舉的集合是一個(gè)數(shù)組時(shí),性能會(huì)好些。例如下面的測(cè)試代碼: 1 class C1 { 2 3 public void Do1() { 4 int[] array = { 1, 2, 3, 4 }; 5 for (int i = 0; i < int.MaxValue/100; i++) { 6 DoIt1(array); 7 } 8 } 9 10 private void DoIt1<T>(IEnumerable<T> array) { 11 foreach (var item in array) { 12 13 } 14 } 15 16 public void Do2() { 17 int[] array = { 1, 2, 3, 4 }; 18 for (int i = 0; i < int.MaxValue/100; i++) { 19 DoIt2(array); 20 } 21 } 22 23 private void DoIt2(int[] array) { 24 foreach (var item in array) { 25 26 } 27 } 28 }
第23行的方法中,編譯器提前已知是一個(gè)數(shù)組的枚舉,所以會(huì)優(yōu)化指令。那么,到底這種優(yōu)化差距有多大呢?我需要試驗(yàn)一下。 第一個(gè)是Do1的結(jié)果,第二個(gè)是Do2的結(jié)果,顯而易見,差距還是相當(dāng)大的,為什么呢?從反編譯的IL代碼來看,第一個(gè)方法使用標(biāo)準(zhǔn)的GetEnumerator機(jī)制,需要?jiǎng)?chuàng)建實(shí)例,而且要調(diào)用Current和MoveNext兩個(gè)方法,更何況,Array的GetValue實(shí)現(xiàn)實(shí)在不夠快。而第二個(gè)方法使用了for的機(jī)制,無需創(chuàng)建實(shí)例,不斷累加和一個(gè)判斷語句即可,性能當(dāng)然高了。 在Linq to Object中,其實(shí)是有這樣考慮的代碼的。例如: public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) { if (source == null) { throw Error.ArgumentNull("source"); } if (selector == null) { throw Error.ArgumentNull("selector"); } if (source is Enumerable.Iterator<TSource>) { return ((Enumerable.Iterator<TSource>)source).Select<TResult>(selector); } if (source is TSource[]) { return new Enumerable.WhereSelectArrayIterator<TSource, TResult>((TSource[])source, null, selector); } if (source is List<TSource>) { return new Enumerable.WhereSelectListIterator<TSource, TResult>((List<TSource>)source, null, selector); } return new Enumerable.WhereSelectEnumerableIterator<TSource, TResult>(source, null, selector); }
創(chuàng)建類和結(jié)構(gòu)的性能差異以及屬性和字段的性能差異下面我還要試驗(yàn)創(chuàng)建類實(shí)例和結(jié)構(gòu)類型,其性能差異到底有多大?會(huì)不會(huì).net的垃圾回收超級(jí)厲害,基本上差異不大呢?當(dāng)然,我也順手測(cè)試了訪問屬性和訪問字段的差別。 1 class C1 { 2 public void Do1() { 3 for (int i = 0; i < int.MaxValue/10; i++) { 4 var p = new PointClass() { X = 1, Y = 2 }; 5 } 6 } 7 public void Do2() { 8 for (int i = 0; i < int.MaxValue/10 ; i++) { 9 var p = new PointClass2() { X = 1, Y = 2 }; 10 } 11 } 12 public void Do3() { 13 for (int i = 0; i < int.MaxValue/10; i++) { 14 var p = new Point() { X = 1, Y = 2 }; 15 } 16 } 17 public void Do4() { 18 for (int i = 0; i < int.MaxValue / 10; i++) { 19 var p = new Point() { XP = 1, YP = 2 }; 20 } 21 } 22 } 23 24 25 class PointClass { 26 public int X { get; set; } 27 public int Y { get; set; } 28 } 29 30 class PointClass2 { 31 public int X; 32 public int Y; 33 } 34 35 struct Point { 36 public int X; 37 public int Y; 38 39 public int XP { get { return X; } set { X = value; } } 40 public int YP { get { return Y; } set { Y = value; } } 41 }
測(cè)試結(jié)果如下: 實(shí)驗(yàn)結(jié)果表明:在計(jì)算密集型的程序中,結(jié)構(gòu)的創(chuàng)建仍然比類要高效的多,另外,屬性和字段的訪問其性能基本相當(dāng)。 |
|