同步更新在獨立博客。 網絡
用過ab作壓力測試的朋友對這張圖應該不陌生,但大多數人並不明白這表明什麼意思,更別說怎麼計算出來的了。雖然ab有不少問題(甚至沒法避免),但仍然值得研究。 併發
一般只關注兩項 socket
Requests per second: 3680.02 [#/sec] (mean) 函數
//每秒事務數:總事務數 / 執行時間 工具
Time per request: 0.230 [ms] (mean, across all concurrent requests) 源碼分析
//事務平均執行時間:執行時間 / 總事務數 性能
但這兩項只能給出大概的結果,詳細的分析還要依賴上圖,下面逐項分析 測試
有Connect,Processing,Waiting,Total四項,詳細的分析在後面源碼分析中給出。 spa
每一項分別有min(最小值),mean(平均值),[+/-sd](方差),median(中位數),max(最大值) code
要計算出以上各項,主要依賴於兩個結構體
struct connection { .... apr_time_t start, /* Start of connection */ connect, /* Connected, start writing */ endwrite, /* Request written */ beginread, /* First byte of input */ done; /* Connection closed */ .... };
struct data { apr_time_t starttime; /* start time of connection */ apr_interval_time_t waittime; /* between request and reading response */ apr_interval_time_t ctime; /* time to connect */ apr_interval_time_t time; /* time for connection */ };
Connect = data.ctime
Processing = data.time - data.ctime
Waiting = data.waittime
Total = data.time
data中的各個字段計算方式以下
data.starttime = connection.start
data.waittime = connection.beginread - beginread .endwrite
data.ctime = connection.connect - connection.start
data.time = connection.done - connection.start
到這裏就能夠明顯的看出來Total = Connect + Processing ,而Waiting 是怎麼計算出來的呢?看這句源碼
s->waittime = ap_max(0, c->beginread - c->endwrite);
就是說Waiting是connection這個結構體中beginread減去endwrite,這表明什麼?從寫入完成到讀取第一個字符,這就是 往返鏈路時間 + 服務端運行時間 + 緩衝區等待時間,前面的好理解,那這個緩衝區等待時間是啥呢?原來內核中有讀/寫緩衝區,咱們調用socket進行write,這個函數執行完數據並不必定已經發送到服務端,而是從用戶空間拷貝到了"寫緩衝區",當發送完畢後再從緩衝區刪除。相應的,服務端返回的數據也會首先儲存在"讀緩衝區",當應用程序拷貝到用戶空間後,才從緩衝區刪除。而Waiting和Processing 的時間只相差一個ab讀取數據的時間,所以在局域網環境下數據量不大時二者相差可能很小。
所以,ab的輸出結果能夠這樣解釋
Connect :socket鏈路創建消耗,表明網絡情況好壞
Processing :寫入緩衝區消耗+鏈路消耗+服務端消耗
Waiting :寫入緩衝區消耗+鏈路消耗+服務端消耗+讀取數據消耗
Total :單個事務總時間
至此,ab輸出結果的前因後果解釋清楚。
可是ab這樣的測試工具備一個最大的問題,就是測試工具自己對測試結果構成影響,特別是設置的併發數較高時,可能測的是ab的性能而不是服務端的性能。正是觀察者效應,觀察者自己對觀察結果構成影響。