Load與CPU利用率
這兩個指標是衡量CPU繁忙程度的關鍵指標。load表示當前系統正在運行和等待運行的進程隊列長度。load越高,表示對cpu資源競爭越激烈,處理器越多,可以支持load越高。 CPU利用率表示一定時間內使用CPU的效率,使用CPU的時間與占用CPU的時間的比值。 處理器核數增加,可以支持的load越高,處理能力越強;而CPU利用率主要與軟件的實現有關,具體而言,與軟件實現的並發度(開啟線程數目,串行度)有關。
同步與異步(編程模型)
同步方式下,阻塞的線程比例會很高,而阻塞線程不被操作系統調度,不占有CPU,導致單位時間內,使用CPU降低,因此IO密集型的應用,CPU利用率普遍比較低。但是同步和異步的方式本身,不會對CPU使用率造成差別,傳統的一線程一請求模式可以通過增加線程的方式提高CPU的利用率, 並且在線程數不是太多的情況下比異步方式性能更好,但異步方式的好處在於線程不會因為IO而處於阻塞狀態(增加阻塞狀態線程的比例), 最終能夠用更少的線程達到高吞吐量,線程過多會因為線程間切換和內存開銷而產生瓶頸。
QPS與RT
QPS:系統每秒處理的請求數,衡量系統吞吐量的指標。
RT:一個請求的響應時間,也可以是一段時間的平均值。
對於一個具體的系統而言,自然是希望RT越低越好,QPS越高越好。為了更高的QPS,最簡單的辦法是增加處理線程數,提高程序的並發度。但是線程數增加到一定程度,會由於各種原因:上下文開銷增大,線程棧占用更多的內存,CPU-CACHE的命中率下降導致QPS無法繼續上升,而且RT也會繼續增加,導致不滿足業務需求,因此會有一個最佳線程數概念。
最佳線程數:剛好消耗完服務器瓶頸資源的臨界線程數(得到最大QPS的線程數)
QPS、RT與最佳線程數關系
RT = CPU Time + Wait Time
最佳線程數=((Wait Time + CPU Time)/CPU Time) * CPU cores * CPU利用率
單線程模型:QPS=1000/RT
多線程模型:QPS = 最佳線程數*1000/RT
= (1000/CPU Time)*(CPU cores * CPU利用率)
如何得到最佳線程數
通過逐步添加線程數,當剛好消耗完服務器的資源時,則到達最佳壓測線程數,此時會有以下特征: 線程數繼續遞增,QPS不變,RT變長,繼續增加,則QPS開始下降,資源瓶頸,可以是CPU,可以是內存,也可以是IO或同步鎖。公式是冷冰冰的,但實際運行的系統沒那麼簡單,否則系統工程師也不必費勁去找系統瓶頸去調優了。 隨著線程數上升,導致上下文開銷增大,線程棧占用更多的內存,CPU-CACHE的命中率下降, 可能達到最佳線程數之前,RT已經不符合業務的期望,滿足一定RT的QPS才是有意義的。
線程池與QPS
前面提到,隨著線程數的遞增,導致上下文開銷增大,線程棧占用更多的內存,CPU-CACHE的命中率下降,從而影響系統的 整體性能。通過線程池(一個線程服務多個請求)可以有效地降低線程數量,緩解上述問題。 所以現在無論是DB服務器(比如mysql),還是應用服務器(比如nginx),實質都是有線程池的。采用線程池,特別對於高並發 場景有很大的意義,線程數量也可以維持在較低的水平。采用線程池模型,使得較少的線程服務請求,可以提高CPU利用率, 同時緩解RT的上升。下圖是mysql啟用線程池與關閉線程池在純讀和讀寫兩種場景下,系統吞吐量的對比。
CPU密集型應用
主要消耗在CPU,減少單次請求的CPU使用時間(比如函數調用量變少),加大並發度(多線程,充分利用多核), 單位時間內可以處理更多的請求,可以提升QPS。當線程數加到一定程度時,大大超過CPU核數,導致大量的 上下文切換,增大RT。
IO密集型應用
1.這種應用比如數據庫,主要時間消耗在IO,假設CPU利用率沒有達到瓶頸,單位時間內請求數目一定
(1)減少IO操作(減少讀寫IO次數),可以減少RT,則QPS基本不變;
(2)減少CPU操作(減少函數調用),可以降低CPU利用率;同時可以減少RT,但不如減少IO明顯。
2.在RT滿足應用需求的情況下,比如每秒10w次請求,RT是10ms,則QPS就是10w,有意義的QPS一定與RT相關。理論上,繼續加 大請求數,QPS還可以繼續往上,同時RT也會繼續往上。當超過1s時,則請求再多,也無法提升QPS。因為一個請求在1s內無法處理完畢。
軟中斷與硬中斷
中斷是指由於接收到外圍硬件(相對於CPU與內存而言)的異步信號或者來自軟件的同步信號而進行相應的硬件/軟件處理。硬中斷是指外圍硬件發給CPU或者內存的異步信號就是硬中斷信號;而軟中斷是軟件本身發給操作系統內核的信號,通常由硬中斷處理程序或系統調用對操作系統內核的中斷。區別軟中斷和硬中斷的一個關鍵點:是否有中斷控制器參與,外設偵測到變化,通過中斷控制器來中斷CPU,是一種隨機的行為。軟中斷直接以一個CPU指令,調用相應的中斷處理程序,是程序可以控制的,磁盤IO和網卡IO都屬於軟中斷。舉個栗子,比如網卡軟中斷,當網卡收到一個數據包後,網卡中斷處理程序會把數據復制到緩沖區,並設置一個標記位,告訴操作系統有事情要做,然後告訴網卡可以繼續接收數據了,當操作系統每次中斷返回時,會檢查標記位,若有,則回調軟中斷的處理函數。
網卡吞吐量優化
由於目前CPU都是多核,可以將網卡設置為多隊列,提高網卡處理效率。當某個隊列收到報文時,觸發相應的中斷,收到中斷的核,對其進行處理。為了避免不同的核處理同一個隊列的報文引起混亂,將每個隊列綁定到唯一的一個核心上。