天天看點

C# 性能優化最佳實踐

1、顯式注冊的evenhandler要顯式登出以避免記憶體洩漏

将一個成員方法注冊到某個對象的事件會造成後者持有前者的引用。在事件登出之前,前者不會被垃圾回收。

由事件引起的記憶體洩漏問題:

對象a訂閱了對象b中的事件

對象a的生命周期遠遠大于對象b

對象a沒有取消訂閱對象b的時間

最終導緻對象b無法釋放

2、控件綁定的資料源批量操作應避免自動重新整理

用戶端批量操作資料時,控件自帶的重新整理操作,會造成不必要的時間消耗

當資料源(如datatable、array、list、observablecollection或其他ilistsource等)被綁定到控件時,批量操作資料時應該斷開綁定或挂起控件的重新整理。

3、減少用戶端與服務端的通信次數

webservice調用并非越少越好,傳輸資料量較大的情況可考慮拆分為多次調用

對于短webservice的調用,應盡量合并以減少互動次數

4、減少用戶端與服務端的通信次數

如非必要,應盡量避免在循環體内重複調用webservice

5、使用泛型來避免裝箱、拆箱操作(減少垃圾回收壓力)

裝箱操作會造成gc壓力;如果發生在集合中,應該使用泛型集合避免。

對于值類型的集合,使用list<t>來代替arraylist,使用dictionary<tkey, tvalue> 來代替hashtable。

6、字元串操作:

<a target="_blank" href="http://blog.csdn.net/jiankunking/article/details/49702803"> c# 字元串操作--減少垃圾回收壓力</a>

7、使用常量避免建立對象

如下例,程式中存在大量 new decimal(0)的代碼,這會導緻小對象頻繁建立及回收;正确的做法是使用 decimal.zero 常量。

8、避免不必要的抛出異常

<a target="_blank" href="http://blog.csdn.net/jiankunking/article/details/49463991">c# 異常處理(catch throw)il分析</a>

9、使用removeall而非removeat進行删除多個元素

使用removeall方法對集合(如list)中的多個元素進行一次性删除時,隻會對list的内部數組做一次resize 操作,效率明顯高于循環調用removeat。

11、反射與動态綁定--減少cpu占用

反射技術是将編譯期間的靜态綁定轉換為延遲到運作期間的動态綁定。

c#主要支援 5 種動态建立對象的方式(時間消耗來自網絡,與我實測的差距挺大,具體測試見下方):

動态建立對象的方式

與direct create

1.type.invokemember

慢40倍以上

2.contructorinfo.invoke

3.activator.createinstance(type)

慢7倍

4.activator.createinstance(assemblyname, typename)

慢1000倍以上

5.assembly.createinstance(typename)

應盡量避免使用反射和動态綁定;如必須使用,要遵循以下原則:

1. 使用接口調用方式将動态綁定改造為早期綁定(direct call)

2. 使用 activator.createinstance(type)方式動态建立對象

3. 使用typeof操作符代替gettype調用

小注:

通過循環建立執行個體記錄時間如下:

加載程式集、擷取類型在循環外部時間如下(這時不同建立方式消耗時間差距挺大):

C# 性能優化最佳實踐

代碼如下:

加載程式集、擷取類型在循環内部時間如下(這時不同建立方式消耗時間差距比較小):

C# 性能優化最佳實踐

12、序列化與反序列化

相對于xml、二進制序列化方式,protobuf效率較高,支援資料量較大

protobuf序列化後的大小是json的1/10,xml格式的1/20,是二進制序列化的1/10

<a target="_blank" href="http://blog.csdn.net/jiankunking/article/details/49742115">c#  序列化</a>

<a target="_blank" href="http://blog.csdn.net/jiankunking/article/details/49739303">c# protobuf-net 序列化</a>

13、資料壓縮

在資料從用戶端傳輸到服務端過程,為減少資料傳輸量,建議對資料進行壓縮處理。

14、