C#編程時應注意的性能處理

GC堆回收

那麼除了經過new對象而達到代的閾(臨界)值時,還有什麼可以致使垃圾堆進行垃圾回收呢? 還可能windows報告內存不足、CLR卸載AppDomain、CLR關閉等其它特殊狀況。算法

或者,咱們還能夠本身經過代碼調用。windows

.NET有GC來幫助開發人員管理內存,而且版本也在不斷迭代。GC幫咱們託管內存,但仍然提供了System.GC類讓開發人員可以輕微的協助管理。 這其中有一個能夠清理內存的方法(並無提供清理某個對象的方法):GC.Collect方法,能夠對全部或指定代進行即時垃圾回收(若是想調試,需在release模式下才有效果)。這個方法儘可能別用,由於它會擾亂代與代間的秩序,從而讓低代的垃圾對象跑到生命週期長的高代中。服務器

GC還提供了,判斷當前對象所處代數、判斷指定代數經歷了多少次垃圾回收、獲取已在託管堆中分配的字節數這樣的三個方法,咱們能夠從這3個方法簡單的瞭解託管堆的狀況。網絡

託管世界的內存不須要咱們打理,咱們沒法從代碼中得知具體的託管對象的大小,你若是想追求對內存最細微的控制,顯然C#並不適合你,不過相似於有關內存把控的這部分功能模塊,咱們能夠經過非託管語言來編寫,而後經過.NET平臺的P/Invoke或COM技術(微軟爲CLR定義了COM接口並在註冊表中註冊)來調用。併發

像FCL中的源碼,不少涉及到操做系統的諸如 文件句柄、網絡鏈接等外部extren的底層方法都是非託管語言編寫的,對於這些非託管模塊所佔用的資源,咱們能夠經過隱式調用析構函數(Finalize)或者顯式調用的Dispose方法經過在方法內部寫上非託管提供的釋放方法來進行釋放。app

像文中示例的socket就將釋放資源的方法寫入Dispose中,析構函數和Close方法均調用Dispose方法以此完成釋放。事實上,在FCL中的使用了非託管資源的類大多都遵循IDispose模式。而若是你沒有釋放非託管資源直接退出程序,那麼操做系統會幫你釋放該程序所佔的內存的。socket

 垃圾回收對性能的影響

還有一點,垃圾回收是對性能有影響的。
GC雖然有不少優化策略,但總之,只要當它開始回收垃圾的時候,爲了防止線程在CLR檢查期間對對象更改狀態,因此CLR會暫停進程中的幾乎全部線程(因此線程太多也會影響GC時間),而暫停的時間就是應用程序卡死的時間,爲此,對於具體的處理細節,GC提供了2種配置模式讓咱們選擇。函數

第一種爲:單CPU的工做站模式,專爲單CPU處理器定作。這種模式會採用一系列策略來儘量減小GC回收中的暫停時間。 
而工做站模式又分爲併發(或後臺)與不併發兩種,併發模式表現爲響應時間快速,不併發模式表現爲高吞吐量。高併發

第二種爲:多CPU的服務器模式,它會爲每一個CPU都運行一個GC回收線程,經過並行算法來使線程能真正同時工做,從而得到性能的提高。性能

咱們能夠經過在Config文件中更改配置來修改GC模式,若是沒有進行配置,那麼應用程序老是默認爲單CPU的工做站的併發模式,而且若是機器爲單CPU的話,那麼配置服務器模式則無效。

若是在工做站模式中想禁用併發模式,則應該在config中運行時節點添加 <gcConcurrent enabled="false" /> 
若是想更改至服務器模式,則能夠添加 <gcServer enabled="true" />。

複製代碼
 <configuration>
        <runtime>
            <!--<gcConcurrent enabled="true|false"/>-->
            <!--<gcServer enabled="true|false"/>-->
        </runtime>
</configuration>
複製代碼

gcConcurrent: https://docs.microsoft.com/zh-cn/dotnet/framework/configure-apps/file-schema/runtime/gcconcurrent-element 
gcServer: https://docs.microsoft.com/zh-cn/dotnet/framework/configure-apps/file-schema/runtime/gcserver-element

  性能建議

雖然咱們能夠選擇適合的GC工做模式來改善垃圾回收時的表現,但在實際開發中咱們更應該注意減小沒必要要的內存開銷。

幾個建議是,減換須要建立大量的臨時變量的模式、考慮對象池、大對象使用懶加載、對固定容量的集合指定長度、注意字符串操做、注意高頻率的隱式裝箱操做、延遲查詢、對於不須要面向對象特性的類用static、須要高性能操做的算法改用外部組件實現(p/invoke、com)、減小throw次數、注意匿名函數捕獲的外部對象將延長生命週期、能夠閱讀GC相關運行時配置在高併發場景注意變換GC模式...

對於.NET中改善性能可延伸閱讀 https://msdn.microsoft.com/zh-cn/library/ms973838.aspx 、 https://msdn.microsoft.com/library/ms973839.aspx

相關文章
相關標籤/搜索