做過性能調優的同學都知道,最怕的不是性能差,而是費了半天勁在細節上死摳,卻忽視了另外一整個對性能有巨大影響的次元,旁邊放着一西瓜卻使勁在芝麻上雕花。針對這種情況,《Performance Tuning: A Comprehensive Guide》的作者梳理了影響性能的幾個次元,具備一定的完整性,新手可以按圖索骥的去調優,老手也可以拿來參考看看是否漏掉了某些事半功倍的方法。
這裡談到的性能是一種統稱,包含響應時間/延遲latency,吞吐量throughput等,也暫時不涉及壓力測試負載測試等手段類似但意圖不同的測試(它們之間的聯系和差別可參考《Restatement: 性能,容量,負載,以及壓力測試》)。
該體系将影響性能的因素分了三大類,分别是:
算法本身,
算法運作環境與所需資源,
以及算法和環境資源的互動。
這三類基本囊括了所有因素。下面我們來看一下裡面的細節。
優化算法本身
這通常是我們一頭紮進去就開始局部優化的地方。常用的手段包括使用各種Profiler來度量CPU時間,記憶體占用率,函數調用次數以進行問題定位,然後實施各種調優方法,比如優化循環,空間換時間等。
選擇合适的資料結構自然算作此類優化,而我們把不同存儲模型等較大規模的優化也歸為此類,比如使用Document代替關系型存儲等。
這個方向的優化可以很快的幫助我們消除一些明顯的程式設計細節引起的瓶頸,但過了初期突飛猛進的階段後,每獲得一點改善,都需要付出巨大的智力上的努力,事半功倍。不要忘了我們還有另外的武器。
優化運作環境與資源
運作環境與資源包括各種軟硬體平台:作業系統,資料庫,運作平台,CPU,記憶體,磁盤,網絡等等。最簡單,最省事的調優方法其實是優化硬體資源,使用快速計算資源代替慢速計算資源,提升資源計算能力:
更快的CPU
更快的本地 IO 裝置:記憶體代替硬碟,SSD代替機械硬碟,增加記憶體減少分頁
更快的網絡 IO 裝置: 光纖及專線增加網絡帶寬,萬兆千兆網卡代替千兆百兆網卡
快速計算資源代替慢速計算資源不局限于同類資源,比如快速存儲代替慢速存儲。跨類型的資源優化也有很好的例子,比如本地計算換網絡傳輸:壓縮傳輸内容是一種常見的性能優化,增加 CPU 壓縮解壓縮時間,但可減少大量網絡傳輸時間。
而運作平台的軟體部分,比如作業系統,資料庫,中間件等,調優的成本要高一些,并且有可能工作量大到不可接受。 比如從 Windows 平台遷移到 Linux 平台,從資料庫 A 切換到資料庫 B,從 EJB 切換到 Spring… 這些最好在初期就考慮好。
這類調優見效快,但受制于預算,及硬體本身的限制。通常很快這類調優會在榨取最後一點計算資源後,遇到瓶頸。
而我們通常談論的焦點,也是目前各種調優實踐最集中的領域,是優化算法和資源間的互動,包括:
減少單台伺服器(或機關計算資源)的處理量
充分利用系統資源
減少不必要的計算
減少不必要的IO
優化算法和資源間的互動
調優一般發生在單台機器處理能力已達上限的情況。一個思路就是把壓力分散到多台機器上,進而使每台機器都能獲得可接受的延遲或吞吐量。
總的原則是分而治之。分的次元包括業務,元件邊界,通路頻率或對系統資源的消耗程度,瓶頸資源等
業務:把大應用按業務分成獨立的互相合作的系統,高層一點的SOA,内層一點的資料庫分庫
元件邊界:web伺服器,應用伺服器,資料庫伺服器,檔案伺服器…
對系統資源的消耗程度:讀寫分離
瓶頸資源:分表分片
一旦按上述次元分好了,還可以在所有次元上應用負載均衡,把通路量分散到不同伺服器。
多線程:隻要原先阻塞的延遲超過了線程切換的延遲,多線程就是值得的。
多程序
異步操作:異步操作可以降低阻塞,減少延遲,代價是程式設計模型的複雜
負載均衡:在”減少單台伺服器(或機關計算資源)的處理量”和”充分利用系統資源”都提到了負載均衡,由此可以看出負載均衡有兩個作用,防止某台伺服器過滿,防止某台伺服器過閑。這真是個 useless 的結論啊,負載均衡按定義不就是幹這個的嗎?
減少不必要的計算次數
緩存計算結果,主要指服務端緩存
減少不必要的 IO 次數
網絡 IO 次數: 用戶端緩存,CDN 緩存。 合并資源以減少請求次數
磁盤 IO 次數: 緩存常用資料
可以看出緩存是減少不必要計算和 IO 的重要手段。緩存的設計主要是根據資源變化頻率對資源進行分類,比如動靜分離等。其前提是恰當的狀态管理,分離無狀态的邏輯和有狀态的邏輯,并付出一定的對一緻性的妥協,運維的複雜為代價。
緩存的适用場景:
熱點不均衡
有效時間不過短
一緻性犧牲程度可接受
以上所有手段可以組合使用,有沖突時再做權衡。