同步更新在独立博客。 网络
用过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的性能而不是服务端的性能。正是观察者效应,观察者自己对观察结果构成影响。