【问题标题】:CherryPy 60x as slow in benchmark with 8 requesting threads compared to 7与 7 个请求线程相比,CherryPy 的基准测试速度慢 60 倍,有 8 个请求线程
【发布时间】:2011-02-14 14:48:45
【问题描述】:

我很好奇为什么在使用ab-c 7(7 个并发线程)对 Python Web 服务器 CherryPy 进行基准测试时,它可以提供每秒 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 应用程序:

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

【问题讨论】:

  • 在 Linux 机器上测试,从 -c7 到 -c8 似乎有更小的、随机的性能下降。大约(每秒1800到每秒600~1200)。该问题似乎发生在最后的请求中,当 -n 更新为 10 000 时消失。您尝试过吗?
  • 谢谢,罗莫尔德。是的,我得到的平均值与-n 10000 完全相同,而且我的最后一次请求似乎没有任何区别。你的机器有多少个内核?

标签: python multithreading cherrypy gil apachebench


【解决方案1】:

在我的 linux 机器上,这是由于从 ab 重新传输了一个 TCP 数据包,虽然我不确定为什么:

No.     Time        Source                Destination           Protocol Info                                                            Delta
  10682 21.218156   127.0.0.1             127.0.0.1             TCP      http-alt > 57246 [SYN, ACK] Seq=0 Ack=0 Win=32768 Len=0 MSS=16396 TSV=17307504 TSER=17306704 WS=6 21.218156
  10683 21.218205   127.0.0.1             127.0.0.1             TCP      57246 > http-alt [ACK] Seq=82 Ack=1 Win=513 Len=0 TSV=17307504 TSER=17307504 SLE=0 SRE=1 0.000049
  10701 29.306438   127.0.0.1             127.0.0.1             HTTP     [TCP Retransmission] GET / HTTP/1.0                             8.088233
  10703 29.306536   127.0.0.1             127.0.0.1             TCP      http-alt > 57246 [ACK] Seq=1 Ack=82 Win=512 Len=0 TSV=17309526 TSER=17309526 0.000098
  10704 29.308555   127.0.0.1             127.0.0.1             TCP      [TCP segment of a reassembled PDU]                              0.002019
  10705 29.308628   127.0.0.1             127.0.0.1             TCP      57246 > http-alt [ACK] Seq=82 Ack=107 Win=513 Len=0 TSV=17309526 TSER=17309526 0.000073
  10707 29.309718   127.0.0.1             127.0.0.1             TCP      [TCP segment of a reassembled PDU]                              0.001090
  10708 29.309754   127.0.0.1             127.0.0.1             TCP      57246 > http-alt [ACK] Seq=82 Ack=119 Win=513 Len=0 TSV=17309526 TSER=17309526 0.000036
  10710 29.309992   127.0.0.1             127.0.0.1             HTTP     HTTP/1.1 200 OK  (text/plain)                                   0.000238
  10711 29.310572   127.0.0.1             127.0.0.1             TCP      57246 > http-alt [FIN, ACK] Seq=82 Ack=120 Win=513 Len=0 TSV=17309527 TSER=17309526 0.000580
  10712 29.310661   127.0.0.1             127.0.0.1             TCP      http-alt > 57246 [ACK] Seq=120 Ack=83 Win=512 Len=0 TSV=17309527 TSER=17309527 0.000089

Wireshark 也没有接收到原始的“GET”数据包。出于某种原因,ab 尝试发送请求并失败,即使 TCP 连接是双 Ak 的就好了。然后客户端的 TCP 堆栈等待几秒钟,等待一个从未发送的数据包被 ACK,当它没有看到 ACK 时,重试并成功。

就个人而言,我不会担心。如果有问题,那不是 CherryPy 的问题。这可能与ab 的内部结构、使用 HTTP/1.0 而不是 1.1、缺少 keepalive、使用 localhost 而不是真正的套接字(模拟网络流量的某些现实而忽略其他)、使用 Windows (wink)、同一接口上的其他流量、CPU 负载……不胜枚举。

【讨论】:

    猜你喜欢
    • 2022-12-11
    • 1970-01-01
    • 2013-06-25
    • 1970-01-01
    • 2013-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-29
    相关资源
    最近更新 更多