看了CoolShell最近的一篇文章《性能調優攻略》我這隻把我比較感興趣的代碼調優部分貼出來留做備份,其餘部分的調優策略能夠點鏈接看原文。以前作的Api監控系統和天然語言的一個情感分析,都用到了海量數據的輸入輸出,對代碼優化這裏感觸甚多,好比數據結構的選擇,異常的處理方式,還有該文中說到的變量類型選擇,多線程控制,在作這種數據量交換很大的模塊時,這些方面就要好好去斟酌了。html
4.2)代碼調優。從個人經驗上來講,代碼上的調優有下面這幾點:web
- 字符串操做。這是最費系統性能的事了,不管是strcpy, strcat仍是strlen,最須要注意的是字符串子串匹配。因此,能用整型最好用整型。舉幾個例子,第一個例子是N年前作銀行的時候,個人同事喜歡把日期存成字符串(如:2012-05-29 08:30:02),我勒個去,一個select where between語句至關耗時。另外一個例子是,我之前有個同事把一些狀態碼用字符串來處理,他的理由是,這樣能夠在界面上直接顯示,後來性能調優的時候,我把這些狀態碼全改爲整型,而後用位操做查狀態,由於有一個每秒鐘被調用了150K次的函數裏面有三處須要檢查狀態,通過改善之後,整個系統的性能上升了30%左右。還有一個例子是,我之前從事的某個產品編程規範中有一條是要在每一個函數中把函數名定義出來,如:const char fname[]=」functionName()」, 這是爲了好打日誌,可是爲何不聲明成 static類型的呢?
- 多線程調優。有人說,thread is evil,這個對於系統性能在某些時候是個問題。由於多線程瓶頸就在於互斥和同步的鎖上,以及線程上下文切換的成本,怎麼樣的少用鎖或不用鎖是根本(好比:多版本併發控制(MVCC)在分佈式系統中的應用 中說的樂觀鎖能夠解決性能問題),此外,還有讀寫鎖也能夠解決大多數是讀操做的併發的性能問題。這裏多說一點在C++中,咱們可能會使用線程安全的智能指針AutoPtr或是別的一些容器,只要是線程安全的,其無論三七二十一都要上鎖,上鎖是個成本很高的操做,使用AutoPtr會讓咱們的系統性能降低得很快,若是你能夠保證不會有線程併發問題,那麼你應該不要用AutoPtr。我記得我上次咱們同事去掉智能指針的引用計數,讓系統性能提高了50%以上。對於Java對象的引用計數,若是我猜的沒錯的話,處處都是鎖,因此,Java的性能問題一直是個問題。另外,線程不是越多越好,線程間的調度和上下文切換也是很誇張的事,儘量的在一個線程裏幹,儘量的不要同步線程。這會讓你有不少的性能。
- 內存分配。不要小看程序的內存分配。malloc/realloc/calloc這樣的系統調很是耗時,尤爲是當內存出現碎片的時候。我之前的公司出過這樣一個問題——在用戶的站點上,咱們的程序有一天不響應了,用GDB跟進去一看,系統hang在了malloc操做上,20秒都沒有返回,重啓一些系統就行了。這就是內存碎片的問題。這就是爲何不少人抱怨STL有嚴重的內存碎片的問題,由於太多的小內存的分配釋放了。有不少人會覺得用內存池能夠解決這個問題,可是實際上他們只是從新發明了Runtime-C或操做系統的內存管理機制,徹底於事無補。固然解決內存碎片的問題仍是經過內存池,具體來講是一系列不一樣尺寸的內存池(這個留給你們本身去思考)。固然,少進行動態內存分配是最好的。說到內存池就須要說一下池化技術。好比線程池,鏈接池等。池化技術對於一些短做業來講(如http服務) 至關至關的有效。這項技術能夠減小連接創建,線程建立的開銷,從而提升性能。
- 異步操做。咱們知道Unix下的文件操做是有block和non-block的方式的,像有些系統調用也是block式的,如:Socket下的select,Windows下的WaitforObject之類的,若是咱們的程序是同步操做,那麼會很是影響性能,咱們能夠改爲異步的,可是改爲異步的方式會讓你的程序變複雜。異步方式通常要經過隊列,要注間隊列的性能問題,另外,異步下的狀態通知一般是個問題,好比消息事件通知方式,有callback方式,等,這些方式一樣可能會影響你的性能。可是一般來講,異步操做會讓性能的吞吐率有很大提高(Throughput),可是會犧牲系統的響應時間(latency)。這須要業務上支持。
- 語言和代碼庫。咱們要熟悉語言以及所使用的函數庫或類庫的性能。好比:STL中的不少容器分配了內存後,那怕你刪除元素,內存也不會回收,其會形成內存泄露的假像,並可能形成內存碎片問題。再如,STL某些容器的size()==0 和 empty()是不同的,由於,size()是O(n)複雜度,empty()是O(1)的複雜度,這個要當心。Java中的JVM調優須要使用的這些參數:-Xms -Xmx -Xmn -XX:SurvivorRatio -XX:MaxTenuringThreshold,還須要注意JVM的GC,GC的霸氣你們都知道,尤爲是full GC(還整理內存碎片),他就像「恐龍特級克賽號」同樣,他運行的時候,整個世界的時間都中止了。
|