80/20法則:程序執行中,80%的時間消耗在20%的代碼上。
優化前,我們首先得找到這20%的關鍵路徑;
各種語言都有專門的工具來找到這20%的關鍵路徑,比如C++經常用到的gprof;
參考《C++的性能優化實踐》
在關鍵路徑上對耗時的計算進行優化;
主要的優化方向為:
減少重復計算、預先計算、延後計算、降低計算代價、不計算;
典型的例子如緩存,將之前相同的計算(查數據庫,讀寫文件)存下來,等待下一次繼續使用;
適用場景:計算結果有有效期,過段時間後需要再次計算;
對於關鍵路徑中比較耗時的計算,預先計算出來,節省每次計算的成本;
預先計算出對照表
關鍵路徑中需要用到的映射關系對照表,將對照表預先計算,在關鍵路徑中直接取用;
將計算提前到初始化期間
比如,內存分配耗時,將其提前到初始化的時間分配,建立內存池;
將計算提前到編譯期間
比如:使用常量表達式,在編譯期間將最終值計算出來,節省這部分的運行時開銷;
相關技術:模版元編程;
適用場景:計算出來的值一直有效,無需再次計算;
將計算耗時延遲到後期,這樣,對於異常情況或其它分支情況,在中途就轉換,不用再計算;
有較多分支條件
將最耗時的計算延後,這樣,可能很多場景在中途就轉到其它分支上,不用計算;
判斷條件中的技巧:a||b a&&b
如果判斷條件比較耗時,將更耗時的放在後面計算;這樣,對於a||b,當a成立時,b就不用再計算了;延遲計算的好處在於可能可以不用計算;
適用場景:分支條件場景;
這是通常能想到的最直接的優化手段,如何能夠直接降低計算的代價;
內存申請從堆上改為棧上
動態內存分配昂貴,將內存分配從堆上改為棧上;
降低靈活性,使用自定制版本的函數代替庫函數;
使用更低級的指令或語言改寫;
在C++中嵌入匯編語言;
使用SSE2等指令集;
使用更優的算法或數據結構;
操作STL容器時,STL中的算法一般比自己手寫的算法要高效,盡量使用STL的算法來替換我們的手寫算法;
參考:
《STL區間成員函數及區間算法總結》
《高效的使用STL》
適用場景:這類優化一般是以降低代碼可讀性為代價的(STL的除外),用於優化的最後階段;
優化的終極方案,不計算;
業務發現
用不到的業務邏輯,廢棄的業務邏輯,仍然存在關鍵路徑中的還在執行的;痛快的刪除它;
卻掉臨時對象開銷
在我們的代碼中,可能會有些臨時對象是不知不覺的,而消除臨時對象,將節省這部分開銷;
參考:《消除臨時對象》
以上是單線程關鍵路徑的優化,接下來,我們聊聊擴展到多核,在多線程上的優化;
Posted by: 大CC | 06AUG,2015
博客:blog.me115.com [訂閱]
Github:大CC