1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
|
# 性能测试
Sogou C++ Workflow是一款性能优异的网络框架,本文介绍我们进行的性能测试,
包括方案、代码、结果,以及与其他同类产品的对比。
更多场景下的实验正在进行中,本文将持续更新。
## HTTP Server
HTTP Client/Server是Sogou C++ Workflow常见的应用场景,
我们首先对Server端进行实验。
### 环境
我们部署了两台相同机器作为Server和Client,软硬件配置如下:
| 软硬件 | 配置 |
|:---:|:---|
| CPU | 40 Cores, x86_64, Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz |
| Memory | 192GB |
| NIC | 25000Mbps |
| OS | CentOS 7.8.2003 |
| Kernel | Linux version 3.10.0-1127.el7.x86_64 |
| GCC | 4.8.5 |
两者间`ping`测得的RTT为0.1ms左右。
### 对照组
我们选择nginx和brpc作为对照组。
选择前者是因为它在生产中部署十分广泛,性能不俗;
对于后者,我们在本次实验中只关注HTTP Server方面的能力,
其他的特性已有[单独的实验][Sogou RPC Benchmark]进行更为详尽的测试。
事实上,我们也对此二者之外的其他某些框架同时进行了实验,
但结果其性能表现相差较远,因此未在本文中体现。
后续我们将选取更多合适的框架加入对比测试中。
### Client工具
本次实验我们使用的压测工具为[wrk][wrk]和[wrk2][wrk2]。
前者适合测试特定并发下的QPS极限和延时,
后者适合在特定QPS下测试延时分布。
我们也尝试过使用其他测试工具,例如[ab][ab]等,但无法打出足够的压力。
有鉴于此,我们也在着手开发基于Sogou C++ Workflow的benchmark工具。
### 变量和指标
一般而言,对网络框架的性能测试,切入的角度可谓纷繁多样。
通过控制不同的变量、观测不同的指标,可以探究程序在不同场景下的适应能力。
本次实验,我们选择其中最普遍常见的变量和指标:
通过控制Client并发度和承载数据的大小,来测试QPS和延时的变化情况。
另外,我们还测试了在掺杂慢请求的正常请求的延时分布。
下面依次介绍两个测试场景。
### 不同并发度和数据长度下的QPS和延时
#### 代码和配置
我们搭建了一个极其简约的HTTP服务器,
忽略掉所有的业务逻辑,
将测试点聚焦在纯粹的网络框架性能上。
代码片段如下,
完整代码移步[这里][benchmark-01 Code]。
```cpp
// ...
auto * resp = task->get_resp();
resp->add_header_pair("Date", timestamp);
resp->add_header_pair("Content-Type", "text/plain; charset=UTF-8");
resp->append_output_body_nocopy(content.data(), content.size());
// ...
```
可以从上述代码中看到,
对于到来的任何HTTP请求,
我们都会返回一段固定的内容作为Body,
并设置必要的Header,
包括代码中指明的`content-type`、`date`,
以及自动填充的`connection`和`content-length`。
HTTP Body的固定内容是在Server启动时随机生成的ASCII字符串,
其长度可以通过启动参数配置。
同时可以配置的还有使用的poller线程数和监听的端口号。
前者我们在本次测试中固定为16,
因此Sogou C++ Workflow将使用16个poller线程和20个handler线程(默认配置)。
对于nginx和brpc,
我们也构建了相同的返回内容,
并为nginx配置了40个进程、
brpc配置了40个线程。
#### 变量
我们控制并发度在`[1, 2K]`之间翻倍增长,
数据长度在`[16B, 64KB]`之间翻倍增长,
两者正交。
#### 指标
鉴于并发度和数据长度组合之后数量较多,
我们选择其中部分数据绘制为曲线。
##### 固定数据长度下QPS与并发度关系
![Concurrency and QPS][Con-QPS]
上图可以看出,当数据长度保持不变,
QPS随着并发度提高而增大,后趋于平稳。
此过程中Sogou C++ Workflow一直有明显优势,
高于brpc和nginx。
特别是数据长度为64和512的两条曲线,
并发度足够的时候,可以保持500K的QPS。
注意上图中nginx-64与nginx-512的曲线重叠度很高,
不易辨识。
##### 固定并发度下QPS与数据长度关系
![Body Length and QPS][Len-QPS]
上图可以看出,当并发度保持不变,
随着数据长度的增长,
QPS保持平稳至4K时下降。
此过程中,Sogou C++ Workflow也一直保持优势。
##### 固定数据长度下延时与并发度关系
![Concurrency and Latency][Con-Lat]
上图可以看出,保持数据长度不变,
延时随并发度提高而有所上升。
此过程中,Sogou C++ Workflow略好于brpc,
大好于nginx。
##### 固定并发度下延时与数据长度关系
![Body Length and Latency][Len-Lat]
上图可以看出,并发度保持不变时,
增大数据长度,造成延时上升。
此过程中,Sogou C++ Workflow好于nginx,
好于brpc。
### 掺杂慢请求的延时分布
#### 代码
我们在上一个测试的基础上,简单添加了一个慢请求的逻辑,
模拟业务场景中可能出现的特殊情况。
代码片段如下,
完整代码请移步[这里][benchmark-02 Code]。
```cpp
// ...
if (std::strcmp(uri, "/long_req/") == 0)
{
auto timer_task = WFTaskFactory::create_timer_task(microseconds, nullptr);
series_of(task)->push_back(timer_task);
}
// ...
```
我们在Server的process里进行判断,
如果访问的是特定的路径,
则添加一个`WFTimerTask`到Series的末尾,
能够模拟一个异步耗时处理过程。
类似地,对brpc使用`bthread_usleep()`函数进行异步睡眠。
#### 配置
在本次实验中,我们固定并发度为1024,数据长度为1024字节,
分别以QPS为20K、100K和200K进行正常请求测试,
测绘延时;
与此同时,有另一路压力,进行慢请求,
QPS是上述QPS的1%,
数据不计入统计。
慢请求的时长固定为5ms。
#### 延时CDF图
![Latency CDF][Lat CDF]
从上图可以看出,当QPS为20K时,
Sogou C++ Workflow略次于brpc;
当QPS为100K时,两者几乎相当;
当QPS为200K时,Sogou C++ Workflow略好于brpc。
总之,可以认为两者在这方面旗鼓相当。
[Sogou RPC Benchmark]: https://github.com/holmes1412/sogou-rpc-benchmark
[wrk]: https://github.com/wg/wrk
[wrk2]: https://github.com/giltene/wrk2
[ab]: https://httpd.apache.org/docs/2.4/programs/ab.html
[benchmark-01 Code]: ../benchmark/benchmark-01-http_server.cc
[benchmark-02 Code]: ../benchmark/benchmark-02-http_server_long_req.cc
[Con-QPS]: https://raw.githubusercontent.com/wiki/sogou/workflow/img/benchmark-01.png
[Len-QPS]: https://raw.githubusercontent.com/wiki/sogou/workflow/img/benchmark-02.png
[Con-Lat]: https://raw.githubusercontent.com/wiki/sogou/workflow/img/benchmark-03.png
[Len-Lat]: https://raw.githubusercontent.com/wiki/sogou/workflow/img/benchmark-04.png
[Lat CDF]: https://raw.githubusercontent.com/wiki/sogou/workflow/img/benchmark-05.png
|