如何编写高性能的C#代码(一)
原文來自互聯網,由長沙DotNET技術社區編譯。如譯文侵犯您的署名權或版權,請聯系小編,小編將在24小時內刪除。
作者介紹:
史蒂夫·戈登(Steve Gordon)是Microsoft MVP,Pluralsight的作者,布萊頓(英國西南部城市)的高級開發人員和社區負責人。
??
對于有追求的.NET開發者來說,如何編寫高性能的C#代碼一直是非??是蟮哪繕?。作為一位.NET方向的MVP,Steve Gordon圍繞這個方向,專門寫了一個系列共7篇博客,主要探討探討支持編寫更多性能,低分配代碼的現代C#和.NET / .NET Core技術和功能。
譯者注:本系列博客的發表時間為2019年2月18日,部分內容可能與新框架代碼有些許不同,請自行驗證。
本系列的文章包括:
1.編寫高性能C#代碼的動機2.使用Benchmark.NET對C# 代碼進行基準測試的簡介3.使用Span?優化代碼的簡介4.使用String.Create創建沒有分配開銷的字符串5.使用JetBrains dotMemory對.NET Core內存流量進行性能分析6.解釋JetBrains dotMemory中的.NET Core內存時間線7.析JetBrains dotMemory中的大對象堆
第一部分:編寫高性能C#代碼的動機
這篇文章標志著我期望一系列與性能相關的文章的開始。我將在目錄中使用該帖子,以訪問這些將來的帖子,并通過討論我的個人動機以學習更多有關編寫高性能C#代碼的個人動機來開始本系列文章。
我不確定100%該系列將帶我去哪里,但我想使用System.IO.Pipelines,.NET Core 3.0中的新JSON解析器以及Span?和Memory?任何相關的主題。
為什么要編寫高性能代碼?
我一直對MVC框架和.NET Core之類的內部原理感興趣。通過了解Microsoft團隊如何設計和構建框架,我感到自己可以提高自己的編碼能力,并且可以更好地使用該產品。自.NET Core和ASP.NET Core 1.0推出以來,性能一直是團隊關注的重點。在過去一年左右的時間里,得到了更大的重視,因此,為了支持高性能方案,引入了新的類型和運行時功能。我看過.NET社區中一些關于性能的著名人物,他們發表了有關性能的文章,因此我決定現在也該深入了解了。
我在Twitter上關注了許多來自Microsoft和.NET社區的優秀人士,并每天獲取鼓舞人心的內容??吹狡渌笰SP.NET Core更快,更高效并在其工作中使用新語言和框架功能的開發人員的帖子非常鼓舞人心。作為一名自學成才的開發人員,我經常覺得有必要學習更多有關我理解的知識。許多與性能相關的新功能對我來說還是個謎。我從概念上理解它們的存在,并且它們正在改進軟件,但是我常常不確定為什么以及更重要的是它們如何做到這一點。
我不懂的東西 我喜歡學習,因此我花了一些時間閱讀博客文章中的性能主題,觀看視頻以及參加會議上的演講。該列表實在太大而無法在此處列出,但是對我來說,一些關鍵靈感是:
?《Writing High-Performance .NET Code[1]》(編寫高性能.NET代碼[2])由本·沃森編寫。?《Pro .NET Memory Management: For Better Code, Performance, and Scalability[3]》by Konrad Kokosa?Blogs[4]?and?talks[5]?by Adam Sitnik?來自亞當Sitnik的一些博客[6]和演講[7]。?Marc Gravell的博客[8]?由.NET社區的許多成員,包括本·亞當斯和David Fowler發表的Tweets?Stephen Toub寫在Microsoft博客
這并非詳盡的清單。我已經從廣泛的社區中獲取了很多精彩的帖子和信息。我非常感謝我們有這么多內容!
什么是性能?
當我在本系列中談論高性能時,我指的是兩個主要概念。首先是使代碼運行更快,從而使操作花費的時間更少。在Web應用程序的上下文中,這可能導致更快的頁面加載時間或更快的API響應。對于處理一些傳入數據以生成輸出的服務工作者風格的應用程序,這與處理的總體吞吐量有關。我認為第二個重要因素是減少內存使用和分配。在我看來,這兩個概念融合為“事半功倍”。
在數據處理工作流中,我將性能視為日常工作重點的一個典型示例。我花了很多時間來開發功能,該功能通常通過AWS隊列來獲取一些數據,并根據該消息執行一些工作。隨著時間的推移,我們的許多服務都在增長和發展,如今正在處理大量數據。一個正在工作的示例就是一個隊列處理器,它每天處理大約17-20百萬條消息。閱讀消息后,工作流將處理數據,對其進行驗證,對其進行充實并對其進行整形以準備存儲到S3和ElasticSearch集群。這個過程并不是很復雜,但是由于數量的原因,我們有一段時間必須水平擴展容器實例以確保我們繼續實現所需的吞吐量。
能否提高效率,減少處理時間和內存消耗?我絕對確定可以。
性能的這兩個支柱通常是內在聯系在一起的,并且影響一個,可以影響另一個。例如,減少代碼中的內存分配可以減少GC負載并減少由收集過程引起的暫停,從而可以提高總體速度。
代碼過早優化?這也是個問題
當在我完成本系列的過程中,這可能會成為許多人爭論的焦點,因此我有必要對這個問題進行討論。我是否過早地進行了優化,并在復雜的、以性能為中心的代碼中花費了太多的時間?
在我的一些示例中可能就是這種情況。我意識到,我正在使用的步驟通常會花費較長的時間編寫代碼,在某些情況下可讀性較低,因此如果將來需要更改代碼,則會增加負擔。我試圖在實驗中突破極限,以找到劃界的正確位置。
我不太喜歡過早優化這個術語,因為在討論中它有時會很快被拋棄,并可能導致性能完全被忽略。我堅信性能應該成為我們或多或少編寫的所有代碼的功能。確定它的重要性以及關注的級別應該是故事計劃中的前期討論。
我認為,團隊應該了解他們正在構建的每個功能的需求。他們應該檢查預期的使用情況和預期的長期增長,以便適當地討論可能影響性能的領域。
有時,這可能意味著不需要采取任何特定的措施,而在其他時候,它可能會確定應在早期考慮的巨大的將來擴展需求,因此應盡早采取措施以避免將來完全重寫。
當我在這里談論性能時,它可能很簡單,例如確保通過Entity Framework進行的查詢使用AsNoTracking支持來減少開銷,或者它可能意味著對字節數據進行自定義解析以避免分配。哪個級別合適的范圍應該通過預先的早期討論來確定。
我并不是在提倡每個人都立即花費數周的時間來重寫現有代碼,以使用Span?和許多其他閃亮的.NET Core功能。我要提倡的是對現有工具的了解,這些工具可以編寫快速,低分配的代碼,以便就何時使用這些代碼提供決策。如果您有代碼或服務難以跟上,請安排一些時間來檢查問題。
對應用程序進行基準測試和性能分析,以了解有關問題所在和適當情況的更多信息,然后開始使用一些新工具來改進代碼并穩定服務。
我舉了一個我維護的隊列處理器的示例,該處理器處理數百萬個事件。兩年半以前,當它第一次用.NET Core 1.0編寫時,我們做出了一些當時有效的選擇。隨著其用途的增加以及我們更加全面地了解需求,現在我們計劃對其進行審查。
我們當前擴展實例以處理負載的解決方案效果很好,但是我敢肯定,如果我們減少頻繁擴展的需求,那么我們可以省錢。作為一家企業,我們需要在變更成本與擴展補償成本之間取得平衡。
對于新的隊列處理器,我們可以從這一經驗中學習,并預先考慮它們的擴展需求。
新服務會迅速發展嗎?它需要處理越來越多的事件或數據嗎?我們能以不同的方式做事,為未來的服務樹立一個更好的先例嗎?我堅信我們可以做到,而且我已經花了一些時間在這些領域構建新想法的原型。
我無論是在工作還是在家里我都會集中時間關注這件目標,并不斷的發現這些功能的局限性,了解什么時候使用它們是合適的,同時我也希望希更多的讀者也參與進來。
摘要
盡管我沒有涵蓋本文中的任何特定內容,但我希望這篇文章能夠解釋為什么我很高興了解更多有關性能功能的信息。在接下來的幾周和幾個月中,我將分享帖子,以分享我對所調查的每件事的經驗。
謝謝閱讀!如果您想了解有關高性能.NET和C#代碼的更多信息,可以在此處[9]查看我的完整博客文章系列。
總結
以上是生活随笔為你收集整理的如何编写高性能的C#代码(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何编写高性能的C#代码(二)
- 下一篇: 从Java转向.NET/C#,Are Y