C#程序員應該養成的程序性能優化寫法


轉載一個別人的文章

隔了很久沒寫東西了,主要是最近比較忙,更主要的是最近比較懶……

其實這篇很早就想寫了

工作和生活中經常可以看到一些程序猿,寫代碼的時候只關注代碼的邏輯性,而不考慮運行效率

其實這對大多數程序猿來說都是沒有問題的

不過作為一只有理想的CodeMonkey,我還是希望給大家分享一些性能優化心得

曾經在網上聽過這樣一句話

程序的可讀性和性能是成反比的

我非常贊同這句話,所以對於那些極度影響閱讀的性能優化我就不在這里贅述了

今天主要說的就是一些舉手之勞即可完成的性能優化

 減少重復代碼

這是最基本的優化方案,盡可能減少那些重復做的事,讓他們只做一次

比較常見是這種代碼,同樣的Math.Cos(angle) 和Math.Sin(angle)都做了2次

優化后

還有另一種 ,在方法中實例化一個對象, 但是這個對象其實是可以復用的

優化后

還有一種是不必要的初始化,比如調用out參數之前,是不需要初始化的

這里的new User()就是不必要的操作,

優化后

 

不要迷信正則表達式

正好在第一個栗子里說到了正在表達式(Regex)對象就順便一起說了

很多人以為正則表達式很快,非常快,超級的快

雖然正則表達式是挺快的,不過千萬不要迷信他,不信你看下面的栗子

有多少人認為正則表達式比較快的,舉個手??

rgwerg2314rvgerger25338811040

結果為10w次循環的時間 ,即使是10個Replace連用,也比Regex好,所以不要迷信他

ConvertQuot1:3518
ConvertQuot2:12479

最后給你們看一個真實的,杯具的栗子

 

合理使用正則表達式

上面說了正則表達式的效率不高,並不是說就不要用他了,至少正則表達式的作用不僅僅如此而已

如果一定要用正則表達式的話也需要注意,能靜態全局公用的盡量全局公用

注意他的第二個參數RegexOptions.Compiled 注釋是  指定將正則表達式編譯為程序集。這會產生更快的執行速度,但會增加啟動時間。

通俗的說就是加了這個枚舉,會使得初始化Regex對象變慢,但是執行字符串查找的時候更快, 不使用的話,初始化很多,查詢比較慢

之前測過相差蠻大的 ,代碼就不比較了,有興趣的可以自己試試相差多少

另外還有一些枚舉項,不確定是否對性能有影響,不過還是按規則使用會比較好

  • RegexOptions.IgnoreCase    // 指定不區分大小寫的匹配,  如果表達式中沒有字母,則不需要設定
  • RegexOptions.Multiline         // 多行模式。更改 ^ 和 $ 的含義….  如果表達式中沒有^和$,則不需要設定
  • RegexOptions.Singleline       // 指定單行模式。更改點 (.) 的含義….  如果表達式中沒有.,則不需要設定

讓編譯器預處理常量的計算

編譯器在編譯程序段的時候 如果發現有一些運算是常量對常量的,那么他會在編譯期間就計算完成,這樣可以使程序在執行時不用重復計算了

比如

ewfwefwef231449524591669

不過編譯器有的時候也不是那么聰明的

ergegege231453256152482

這個時候就需要我們幫助一下了

yhrhr231453426932297

給他加一個括號,讓他知道應該先計算常量,這樣就可以在編譯期間進行運算了

字符串比較

這個可能很多人知道了,但還是提一下

1,2最慢 3較快 4,5最快

1,2幾乎沒區別 4,5幾乎沒區別

不過這個只適用於比較null和空字符串,如果是連續的空白就是string.IsNullOrWhiteSpace最快了,不過這個方法2.0里面沒有

所以2.0可以這樣 (s+””).trim() == 0

這里的關鍵就是 s + “”  這個操作可以把null轉換為””

注意第二個參數只能是””或string.Empty 這樣的累加幾乎是不消耗時間的,如果第二個參數是” “(一個空格)這個時間就遠遠不止了

字符串拼接

字符串累加,這個道理和Regex一樣,不要盲目崇拜StringBuilder

在大量(或不確定的)string拼接的時候,StringBuilder確實可以起到提速的作用

而少數幾個固定的string累加的時候就不需要StringBuilder 了,畢竟StringBuilder 的初始化也是需要時間的

感謝殘蛹 博友提供的說明

ps: 這段我確實記得我是寫過的來着,不知道怎么的,發出來的時候就不見了…..

rghergerer231515097401697

此外還有一個string.Concat方法,該方法可以小幅度的優化程序的速度,幅度很小

他和string.Join的區別在於沒有間隔符號(我之前常用string.Join(“”,a,b,c,d),不要告訴我只有我一個人這么干)

另一種經常遇到的字符串拼接

對於這種情況有2中優化的方案

對於3.5以上可以直接使用Linq輔助,這種方案代碼少,但是性能相對差一些

對於非3.5或對性能要求極高的場合

 

bool類型的判斷返回

這種現象常見於新手程序員中

 

類型的判斷

一般類型的判斷有2種形式

1,這種屬於代碼比較好寫,但是性能比較低, 原因就是GetType()的時候消耗了很多時間

2,這種屬性寫代碼麻煩,但是性能很高的類型

其實有個中間之道,既可以保證性能又可以比較好寫

大部分情況下 這個是可以用的 如果你自己有個類型實現了IConvertible,然后返回TypeCode.Int32 就不再這個討論范圍之內了

使用枚舉作為索引

下面這個是一個真實的例子,為了突出重點,做了部分修改,刪除了多余的分支,源代碼中不只4個

優化后

不過有的時候,枚舉不一定都是連續的數字,那么也可以使用Dictionary

這種優化在分支比較多的時候很好用,少的時候作用有限

字符類型Char,分支判斷時的處理技巧

這部分內容比較復雜,而且適用范圍有限,如果平時用不到的就可以忽略了

在處理字符串對象的時候,有時會需要判斷char的值然后做進一步的操作

這里有一種空間換時間的優化方式, 雖說是空間換時間,但是實際浪費的空間不會很多,因為char最多只有65536長度

原先僅特殊符號一部分就需要判斷12次,修改過后只判斷一次就可以得到結果了

這方面的栗子在我的Json組件(代碼)(文章1,2,3)中也有使用

 摘取部分blqw.Json的代碼

結束了…還要后續嗎?…貌似我又要懶一段時間

我寫的文章,除了純代碼,其他的都是想表達一種思想,一種解決方案.希望各位看官不要局限於文章中的現成的代碼,要多關注整個文章的主題思路,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM