成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Lambda表達式:要性能還是要清晰的代碼?

開發 后端
本文分析了Lambda表達式實現序列的兩種寫法,并建議與其過早的考慮代碼性能,還是代碼的清晰更加重要。

在上文的***個示例中,我們演示了如何使用Lambda表達式配合.NET 3.5中定義的擴展方法來方便地處理集合中的元素(篩選,轉化等等)。不過有朋友可能會提出,那個“普通寫法”并非是性能***的實現方法。方便起見,也為了突出“性能”方面的問題,我們把原來的要求簡化一下:將序列中的偶數平方輸出為一個列表。按照那種“普通寫法”可能就是:

  1. static List< int> EvenSquare(IEnumerable< int> source)  
  2. {  
  3.     var evenList = new List< int>();  
  4.     foreach (var i in source)  
  5.     {  
  6.         if (i % 2 == 0) evenList.Add(i);  
  7.     }  
  8.  
  9.     var squareList = new List< int>();  
  10.     foreach (var i in evenList) squareList.Add(i * i);  
  11.  
  12.     return squareList;  
  13. }  
  14.  

從理論上來說,這樣的寫法的確比以下的做法在性能要差一些:

  1. static List< int> EvenSquareFast(IEnumerable< int> source)  
  2. {  
  3.     List< int> result = new List< int>();  
  4.     foreach (var i in source)  
  5.     {  
  6.         if (i % 2 == 0) result.Add(i * i);  
  7.     }  
  8.  
  9.     return result;  
  10. }  
  11.  

在第二種寫法直接在一次遍歷中進行篩選,并且直接轉化。而***種寫法會則根據“功能描述”將做法分為兩步,先篩選后轉化,并使用一個臨時列表進行保存。在向臨時列表中添加元素的時候,List< int>可能會在容量不夠的時候加倍并復制元素,這便造成了性能損失。雖然我們通過“分析”可以得出結論,不過實際結果還是使用CodeTimer來測試一番比較妥當:

  1. List< int> source = new List< int>();  
  2. for (var i = 0; i <  10000; i++) source.Add(i);  
  3.  
  4. // 預熱  
  5. EvenSquare(source);  
  6. EvenSquareFast(source);  
  7.  
  8. CodeTimer.Initialize();  
  9. CodeTimer.Time("Normal", 10000, () => EvenSquare(source));  
  10. CodeTimer.Time("Fast", 10000, () => EvenSquareFast(source));  
  11.  

我們準備了一個長度為10000的列表,并使用EvenSquare和EvenSquareFast各執行一萬次,結果如下:

  1. Normal  
  2.         Time Elapsed:   3,506ms  
  3.         CPU Cycles:     6,713,448,335  
  4.         Gen 0:          624  
  5.         Gen 1:          1  
  6.         Gen 2:          0  
  7.  
  8. Fast  
  9.         Time Elapsed:   2,283ms  
  10.         CPU Cycles:     4,390,611,247  
  11.         Gen 0:          312  
  12.         Gen 1:          0  
  13.         Gen 2:          0  

Lambda表達式的執行:性能比對與結論

結果同我們料想中的一致,EvenSquareFast無論從性能還是GC上都領先于EvenSquare方法。不過,在實際情況下,我們該選擇哪種做法呢?如果是我的話,我會傾向于選擇EvenSquare,理由是“清晰”二字。

EvenSquare雖然使用了額外的臨時容器來保存中間結果(因此造成了性能和GC上的損失),但是它的邏輯和我們需要的功能較為匹配,我們可以很容易地看清代碼所表達的含義。至于其中造成的性能損失在實際項目中可以說是微乎其微的。因為實際上我們的大部分性能是消耗在每個步驟的功能上,例如每次Int32.Parse所消耗的時間便是一個簡單乘法的幾十甚至幾百倍。因此,雖然我們的測試體現了超過50%的性能差距,不過由于這只是“純遍歷”所消耗的時間,因此如果算上每個步驟的耗時,性能差距可能就會變成10%,5%甚至更低。

當然,如果是如上述代碼那樣簡單的邏輯,則使用EvenSquareFast這樣的實現方式也沒有任何問題。事實上,我們也不必強求將所有步驟完全合并(即僅僅使用1次循環)或完全分開。我們可以在可讀性與性能之間尋求一種平衡,例如將5個步驟使用兩次循環來完能是更合適的方式。

說到“分解循環”,其實這類似于Martin Fowler在他的重構網站所上列出的重構方式之一:“Split Loop”。雖然Split Loop和我們的場景略有不同,但是它也是為了代碼的可讀性而避免將多種邏輯放在一個循環內。將循環拆開之后,還可以配合“Extract Method”或“Replace Temp with Query”等方式實現進一步的重構。自然,它也提到拆分后的性能影響:

You often see loops that are doing two different things at once, because they can do that with one pass through a loop. Indeed most programmers would feel very uncomfortable with this refactoring as it forces you to execute the loop twice - which is double the work.

But like so many optimizations, doing two different things in one loop is less clear than doing them separately. It also causes problems for further refactoring as it introduces temps that get in the way of further refactorings. So while refactoring, don't be afraid to get rid of the loop. When you optimize, if the loop is slow that will show up and it would be right to slam the loops back together at that point. You may be surprised at how often the loop isn't a bottleneck, or how the later refactorings open up another, more powerful, optimization.

這段文字提到,當拆分之后,您可能會發現更好的優化方式。高德納爺爺也認為“過早優化是萬惡之源”。這些說法都在“鼓勵”我們將程序寫的更清晰而不是“看起來”更有效率。

以上便分析了使用C# Lambda表達式編碼時需要優先考慮代碼清晰度的理由。

【編輯推薦】

  1. .NET Lambda表達式的函數式特性:索引示例
  2. .NET Lambda表達式的語義:字符串列表范例
  3. 使用.NET 3.5 Lambda表達式實現委托
  4. 各版本.NET委托的寫法回顧
  5. C# Actor模型開發實例:網絡爬蟲
責任編輯:yangsai 來源: 老趙點滴
相關推薦

2012-06-26 10:03:58

JavaJava 8lambda

2009-09-09 13:01:33

LINQ Lambda

2009-09-15 15:18:00

Linq Lambda

2022-12-05 09:31:51

接口lambda表達式

2009-09-11 09:48:27

Linq Lambda

2024-03-25 13:46:12

C#Lambda編程

2009-08-27 09:44:59

C# Lambda表達

2009-09-15 17:30:00

Linq Lambda

2009-09-17 09:44:54

Linq Lambda

2009-09-17 10:40:22

Linq Lambda

2009-07-09 09:51:07

Lambda表達式C#

2020-10-16 06:40:25

C++匿名函數

2021-11-10 09:45:06

Lambda表達式語言

2013-04-07 15:44:26

Java8Lambda

2009-08-10 09:41:07

.NET Lambda

2009-09-09 17:14:17

Linq lambda

2013-04-10 10:58:19

LambdaC#

2009-08-27 09:57:50

C# Lambda表達

2009-08-31 17:11:37

Lambda表達式

2009-09-17 09:09:50

Lambda表達式Linq查詢
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产91久久久久蜜臀青青天草二 | 久久久国产精品 | 亚洲成人av | 精产国产伦理一二三区 | 久久久久综合 | 国产精品国产馆在线真实露脸 | 大久| 一区二区三区视频免费观看 | 成人高清在线视频 | 欧洲亚洲精品久久久久 | 久久久久久久成人 | 日韩成人免费av | 亚洲va欧美va人人爽午夜 | 国产欧美一区二区三区在线播放 | 男人亚洲天堂 | 久久亚洲国产精品日日av夜夜 | 亚洲影音先锋 | 精品在线免费看 | 成人免费视频观看视频 | 久久久久免费精品国产 | 亚洲一区 | 久www| 欧美日韩国产一区二区三区 | 免费av手机在线观看 | 超碰av在线 | 亚洲天堂久久 | 亚洲精品9999| 亚洲精品久久久久中文字幕二区 | re久久| 一级黄色片毛片 | h视频在线播放 | 99re在线播放 | 久久亚洲国产精品 | 日日噜噜夜夜爽爽狠狠 | 国产精品亚洲第一区在线暖暖韩国 | 成人国产精品久久 | 91精品一区二区 | 亚洲精品永久免费 | 亚洲乱码一区二区三区在线观看 | 日日夜夜精品视频 | 日本在线免费看最新的电影 |