CherryPy 在基准测试中,8 个请求线程比 7 个请求慢 60 倍
我很好奇为什么在使用 ab
,使用 -c 7
(7 个并发线程),它可以服务器 1500 个请求/秒(大约是我所期望的),但是当我更改为 -c 8
> 它下降到 25 个请求/秒。我在运行 Python 2.6、有四个核心的 64 位 Windows 计算机上运行 numthreads=10 的 CherryPy(但如果我使用 numthreads=8 或 20,则不会有什么不同)。
我半怀疑 Python GIL 是问题的一部分,但我不知道为什么只有当我有多达 8 个并发请求线程时才会发生这种情况。在四核机器上,我预计它可能会在 -c 4
处发生变化,但事实并非如此。
我正在使用 web.py 附带的单文件 CherryPy Web 服务器,这是我使用的 WSGI 应用程序m 测试:
from web.wsgiserver import CherryPyWSGIServer
def application(environ, start_response):
start_response("200 OK", [("Content-type", "text/plain")])
return ["Hello World!",]
server = CherryPyWSGIServer(('0.0.0.0', 80), application, numthreads=10)
try:
server.start()
except KeyboardInterrupt:
server.stop()
7 个和 8 个并发线程的 ab
输出为:
C:\\> ab -n 1000 -c 7 http://localhost/
...
Concurrency Level: 7
Time taken for tests: 0.670 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 130000 bytes
HTML transferred: 12000 bytes
Requests per second: 1492.39 [#/sec] (mean)
Time per request: 4.690 [ms] (mean)
Time per request: 0.670 [ms] (mean, across all concurrent requests)
Transfer rate: 189.46 [Kbytes/sec] received
C:\\> ab -n 1000 -c 8 http://localhost/
...
Concurrency Level: 8
Time taken for tests: 7.169 seconds
Complete requests: 158
Failed requests: 0
Write errors: 0
Total transferred: 20540 bytes
HTML transferred: 1896 bytes
Requests per second: 22.04 [#/sec] (mean)
Time per request: 362.973 [ms] (mean)
Time per request: 45.372 [ms] (mean, across all concurrent requests)
Transfer rate: 2.80 [Kbytes/sec] received
I'm curious why when benchmarking Python web server CherryPy using ab
, with -c 7
(7 concurrent threads) it can server 1500 requests/s (about what I expect), but when I change to -c 8
it drops way down to 25 requests/s. I'm running CherryPy with numthreads=10 (but it doesn't make a different if I use numthreads=8 or 20) on a 64-bit Windows machine with four cores running Python 2.6.
I'm half-suspecting the Python GIL is part of the issue, but I don't know why it only happens when I get up to 8 concurrently-requesting threads. On a four core machine I'd expect it might change at -c 4
, but this is not the case.
I'm using the one-file CherryPy web server that comes with web.py, and here's the WSGI app that I'm testing against:
from web.wsgiserver import CherryPyWSGIServer
def application(environ, start_response):
start_response("200 OK", [("Content-type", "text/plain")])
return ["Hello World!",]
server = CherryPyWSGIServer(('0.0.0.0', 80), application, numthreads=10)
try:
server.start()
except KeyboardInterrupt:
server.stop()
The ab
output for 7 and 8 concurrent threads is:
C:\\> ab -n 1000 -c 7 http://localhost/
...
Concurrency Level: 7
Time taken for tests: 0.670 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 130000 bytes
HTML transferred: 12000 bytes
Requests per second: 1492.39 [#/sec] (mean)
Time per request: 4.690 [ms] (mean)
Time per request: 0.670 [ms] (mean, across all concurrent requests)
Transfer rate: 189.46 [Kbytes/sec] received
C:\\> ab -n 1000 -c 8 http://localhost/
...
Concurrency Level: 8
Time taken for tests: 7.169 seconds
Complete requests: 158
Failed requests: 0
Write errors: 0
Total transferred: 20540 bytes
HTML transferred: 1896 bytes
Requests per second: 22.04 [#/sec] (mean)
Time per request: 362.973 [ms] (mean)
Time per request: 45.372 [ms] (mean, across all concurrent requests)
Transfer rate: 2.80 [Kbytes/sec] received
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在我的 Linux 机器上,这是由于从
ab
重新传输了 TCP 数据包,尽管我不太确定原因:Wireshark 也没有拾取原始的“GET”数据包。由于某种原因,
ab
尝试发送请求并失败,即使 TCP 连接是双重确认的也是如此。然后,客户端的 TCP 堆栈等待几秒钟,等待从未发送的数据包得到 ACK,当它没有看到 ACK 时,重试并成功。就我个人而言,我不会担心这个。如果出现问题,那不是 CherryPy 的问题。这可能与 ab 的内部结构、使用 HTTP/1.0 而不是 1.1、缺乏 keepalive、使用 localhost 而不是真正的套接字(模拟网络流量的一些现实情况)有关。忽略其他)、Windows 的使用(眨眼)、同一接口上的其他流量、CPU 上的负载……这样的例子不胜枚举。
On my linux box, it's due to the retransmission of a TCP packet from
ab
, although I'm not exactly sure why:The original "GET" packet wasn't picked up by Wireshark either. For some reason,
ab
tries to send a request and fails, even though the TCP connection was double-ACk'd just fine. Then the client's TCP stack waits for a few seconds for a packet that was never sent to be ACK'd, and when it sees no ACK, retries and succeeds.Personally, I wouldn't worry about it. If there's a problem, it's not one with CherryPy. It could be related to the internals of
ab
, the use of HTTP/1.0 instead of 1.1, the lack of keepalive, the use of localhost instead of a real socket (which simulates some realities of network traffic and ignores others), the use of Windows (wink), other traffic on the same interface, load on the CPU...the list goes on and on.