搜尋
首頁後端開發C#.Net教程編寫高效能 .NET的實例教學課程

編寫高效能 .NET的實例教學課程

Jun 25, 2017 am 09:08 AM
.net程式碼編寫翻譯高效能

減少分配率

這個幾乎不用解釋,減少了記憶體的使用量,自然就減少GC回收時的壓力,同時降低了記憶體碎片與CPU的使用量。你可以用一些方法來達到這個目的,但它可能會與其它設計相衝突。

你需要在設計物件時仔細檢查每個它並問自己:

  1. #我真的需要這個物件嗎?

  2. 這個欄位是我需要的嗎?

  3. 我能減少陣列的尺寸嗎?

  4. 我能縮小primitives的尺寸嗎(用Int32替換Int64,其它)?

  5. 這些對象,是否只有在極少數情況下,或只有初始化的時候才會被使用?

  6. 是否能將一些類別轉為結構體使他們在堆疊上分配或成為某個物件的一部分?

  7. 我是否分配了大量內存,但實際上只使用其中很小的一部分?

  8. 我可以從其它地方拿到相關資料?

小故事:在服務端一個回應請求的函數裡,我們發現在一次請求裡會分配一些比記憶體段要大的記憶體。這樣導致每次請求我們都會觸發一次完整的GC,這是因為CLR要求所有的0代物件都在一個記憶體段裡,目前分配的記憶體段滿了,就會開闢一個新的記憶體段,同時對原先的記憶體段做一次2代的回收。這不是一個好的實現,因為我們除了減少記憶體分配外別無它法。

最重要的規則

對於垃圾回收的高效能程式設計有一個基本規則,事實上也是程式碼設計的指導規則。

要收集的物件要麼在0代,要麼不存在
Collect objects in gen 0 or not at all.

#不同的是,你希望一個物件擁有極短的生命週期,在GC的時候永遠不要碰到它,或者,如果你做不到這一點,它們應該去2代,盡可能的快,永遠的呆在那,永遠不會被回收。這意味著你永遠保持對長生命週期物件的引用。通常,也意味著物件可重複使用,尤其是在大物件堆裡的物件。
GC每高一個世代的回收會比上一個世代更耗時。如果你想保持許多0,1代和少量的2代物件。即使開啟後台GC做2代做回收,也會消耗相當CPU運算量,你可能更願意將這部分的CPU消耗給應用程序,而不是GC。

Note 你可能聽過一個說法,每10次0代的回收會產生一次1代的回收,每10次1代的回收會產生1次2代的回收。這其實是不正確的,但你要明白,你要盡量產生多次快速的0代回收,以及少量的2代回收。

你最好避免進行1代回收,主要是因為已經從0代提升到1代的對象,會在這時候被轉入2代。 1代是物件進入2代的一個緩衝區。
理想情況下,你分配的每一個物件應該在下一次0代回收前結束生命週期。你可以測量兩次GC的時間間隔,並將其與應用程式裡物件的生命週期長度做對比。有關如何使用工具測量生命週期的信息,可以在本章結尾看到。
你可能不習慣這樣思考,但這規則切入了應用程式的方方面面,你需要經常思考它,在心態要做根本的轉變,這樣才能實現這個最重要的規則。

縮短物件的生命週期

一個物件的作用範圍越短,在下一個GC出現時,它被提升到下一代的機會就越小。一般來說,在你需要之前,不要創建物件。
同時,當物件創建的代價如此之高時,異常就可以在較早的時候創建,這樣不會幹擾到其他處理邏輯。
另外,你也要確保物件盡可能早的退出作用域。對於局部變量,你可以在最後一次使用後,甚至在方法結束前將其生命週期結束。你可一個用{}將程式碼包含起來,這不會對你的運行產生影響,但編譯器會認為在這個範圍的物件已經完成了他的生命週期,不再被使用了。如果需要呼叫物件的方法,盡量減少第一次和最後一次的時間間隔,以便GC儘早的回收物件。
如果物件關聯(引用)了一些會長時間保持的對象,則需要解除他們的引用關係。你可能會有更多的空值檢查(null判斷),這可能會讓程式碼變得更複雜。也會在物件的可用狀態(always having full state available)上與效率之間造成緊張關係,特別是調試的時候。
解決的一種方法是,將要清空的物件轉換為另一種方式存在,例如:日誌訊息,這樣在後面的偵錯時可以查詢到相關資訊。
另一個方法是為程式碼增加可設定選項(不解除物件之間的關係):執行程式(或執行程式裡特定的一個部分,例如一個特定的請求),在這個模式中沒有解除對象引用關係,而是盡可能讓物件一直保持方便調試。

減少物件層次的深度

如本章開頭所述,GC在回收時會順著物件的參考關係進行遍歷。在伺服器GC模式,GC會以多執行緒方式執行,但如果一個執行緒需要處理一個物件層次很深,則所有已經處理完的執行緒都需要等待這個執行緒完成處理後才能退出。在今後的CLR版本裡,你可以不用太關注這個問題,GC在多執行緒執行時會採用更好的標記演算法來做負載平衡。但如果你物件層次很深,這個問題還是要注意一下的。

減少物件之間的引用

這與上節的深度有關,但也有一些其它的因素。
一個物件如果引用了很多物件(數組,List吧),那它將花很多時間在遍歷物件上。是GC造成長時間的問題,因為它有一個複雜的關係圖。
另一個問題是,如果無法輕鬆的確定物件有多少引用關係,那麼你就無法準確的預測物件的生命週期。減少這種複雜度是相當有必要的,它不但可以讓程式碼更健壯,同時也方便調試以及獲得更好的效能。
另外,也要注意不同世代物件之間的引用也會導致GC的效率低下,特別是舊物件對新物件的引用。例如,如果2代對像在0代對象裡有引用關係,那麼每次發生0代的GC時,也需要掃描部分2代對象,看看他們是否仍保持在0代對象的引用上。雖然這不是一次完整的GC,但它仍然是不要的工作,你應該盡量避免這種情況。

避免釘住物件(Pinning)

釘住物件可以保證從託管程式碼傳送資料到本機程式碼的安全性。常見的有數組和字串。如果你的程式碼不需要與本地程式碼做交互,則不用考慮它的效能開銷。
釘住物件就是讓物件在垃圾回收(壓縮階段)時無法移動他。雖然釘住物件不會造成太多開銷,但它會妨礙到GC的回收操作,增加記憶體碎片的可能性。 GC在回收時會記錄物件的位置,以便在重修分配時利用它們之間的空間,但如果釘住的物件很多,會導致記憶體碎片的增加。
釘可以是顯示的也可以使隱式的。顯示的是使用GCHandle時用GCHandleType.Pinned參數進行設置,或在unsafe模式下使用 fixed 關鍵字。使用fixed關鍵字和GCHandle的差異在於是否會顯示呼叫Dispose方法。使用fixed雖然很方便,但是不能在非同步情況下使用,但還是可以建立一個句柄物件(GCHandle),在回呼時傳回並處理。
隱式的釘住物件比較常見,但也更難排查,也更難移除。最明顯的例子就是透過平台呼叫(P/Invoke)將物件傳遞給非託管程式碼。這不只是你的程式碼—--你經常呼叫的一些託管API,其實也是會呼叫本機程式碼,也會將物件釘住。
CLR也會將自己的一些資料釘住,但這通常不需要你來關心。
理想情況下,你應該盡可能的不要釘住對象。如果不能做到,那麼遵循先前的重要規則,盡可能讓這些被釘的對象儘早釋放。如果物件只是簡單的被釘住後釋放,那麼就不會有多少機會影響回收操作。你同時也要避免同時釘住很多個物件。被釘的對像被交換到2代或在LOH裡分配會稍微好些。根據這個規則,你可以在大物件堆上分配一個大的緩衝區,並根據實際需要自己對緩衝區做管理。或在小物件對上分配緩衝區,然後在釘住他們之前,使他們升級到2代。這樣比你直接將對象釘在0代上要好。

以上是編寫高效能 .NET的實例教學課程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
C#.NET用於網絡,桌面和移動開發C#.NET用於網絡,桌面和移動開發Apr 25, 2025 am 12:01 AM

C#和.NET適用於Web、桌面和移動開發。 1)在Web開發中,ASP.NETCore支持跨平台開發。 2)桌面開發使用WPF和WinForms,適用於不同需求。 3)移動開發通過Xamarin實現跨平台應用。

C#.NET生態系統:框架,庫和工具C#.NET生態系統:框架,庫和工具Apr 24, 2025 am 12:02 AM

C#.NET生態系統提供了豐富的框架和庫,幫助開發者高效構建應用。 1.ASP.NETCore用於構建高性能Web應用,2.EntityFrameworkCore用於數據庫操作。通過理解這些工具的使用和最佳實踐,開發者可以提高應用的質量和性能。

將C#.NET應用程序部署到Azure/AWS:逐步指南將C#.NET應用程序部署到Azure/AWS:逐步指南Apr 23, 2025 am 12:06 AM

如何將C#.NET應用部署到Azure或AWS?答案是使用AzureAppService和AWSElasticBeanstalk。 1.在Azure上,使用AzureAppService和AzurePipelines自動化部署。 2.在AWS上,使用AmazonElasticBeanstalk和AWSLambda實現部署和無服務器計算。

C#.NET:強大的編程語言簡介C#.NET:強大的編程語言簡介Apr 22, 2025 am 12:04 AM

C#和.NET的結合為開發者提供了強大的編程環境。 1)C#支持多態性和異步編程,2).NET提供跨平台能力和並發處理機制,這使得它們在桌面、Web和移動應用開發中廣泛應用。

.NET框架與C#:解碼術語.NET框架與C#:解碼術語Apr 21, 2025 am 12:05 AM

.NETFramework是一個軟件框架,C#是一種編程語言。 1..NETFramework提供庫和服務,支持桌面、Web和移動應用開發。 2.C#設計用於.NETFramework,支持現代編程功能。 3..NETFramework通過CLR管理代碼執行,C#代碼編譯成IL後由CLR運行。 4.使用.NETFramework可快速開發應用,C#提供如LINQ的高級功能。 5.常見錯誤包括類型轉換和異步編程死鎖,調試需用VisualStudio工具。

揭開c#.net的神秘面紗:初學者的概述揭開c#.net的神秘面紗:初學者的概述Apr 20, 2025 am 12:11 AM

C#是一種由微軟開發的現代、面向對象的編程語言,.NET是微軟提供的開發框架。 C#結合了C 的性能和Java的簡潔性,適用於構建各種應用程序。 .NET框架支持多種語言,提供垃圾回收機制,簡化內存管理。

C#和.NET運行時:它們如何一起工作C#和.NET運行時:它們如何一起工作Apr 19, 2025 am 12:04 AM

C#和.NET運行時緊密合作,賦予開發者高效、強大且跨平台的開發能力。 1)C#是一種類型安全且面向對象的編程語言,旨在與.NET框架無縫集成。 2).NET運行時管理C#代碼的執行,提供垃圾回收、類型安全等服務,確保高效和跨平台運行。

C#.NET開發:入門的初學者指南C#.NET開發:入門的初學者指南Apr 18, 2025 am 12:17 AM

要開始C#.NET開發,你需要:1.了解C#的基礎知識和.NET框架的核心概念;2.掌握變量、數據類型、控制結構、函數和類的基本概念;3.學習C#的高級特性,如LINQ和異步編程;4.熟悉常見錯誤的調試技巧和性能優化方法。通過這些步驟,你可以逐步深入C#.NET的世界,並編寫高效的應用程序。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。