使用select()的简单TCP服务器,为什么“最长请求”如此之高?

时间:2009-09-26 15:40:17

标签: php performance tcp

我正在使用select()方法实现一个简单的TCP服务器 - 一切都很好并且性能完全可以接受,但是当使用ab(apachebench)进行基准测试时,“最长请求”与平均时间相比非常高:

我正在使用:ab -n 5000 -c 20 http://localhost:8000/

片段:

Requests per second:    4262.49 [#/sec] (mean)
Time per request:       4.692 [ms] (mean)
Time per request:       0.235 [ms] (mean, across all concurrent requests)

Percentage of the requests served within a certain time (ms)
  50%      2
  66%      2
  75%      2
  80%      2
  90%      2
  95%      3
  98%      3
  99%      4
 100%    203 (longest request)

和apache一样:

Requests per second:    5452.66 [#/sec] (mean)
Time per request:       1.834 [ms] (mean)
Time per request:       0.183 [ms] (mean, across all concurrent requests)

Percentage of the requests served within a certain time (ms)
  50%      1
  66%      2
  75%      2
  80%      2
  90%      3
  95%      3
  98%      4
  99%      4
 100%      8 (longest request)

作为参考,我使用的是stream_select,套接字是非阻塞的。

这是使用select()调用的常见效果吗?
我应该担心有哪些性能方面的考虑因素?

更新

当使用并发值< = 6时,最长的请求是“正常”(大约是平均值的2倍或3倍),但是6以上的任何内容都会变得疯狂(例如,7个并发请求可能会以20为基准进行基准测试,或大约200ms)。

UPDATE2:

在用等效的套接字函数替换流函数和一些正确的测试/基准测试之后,问题不再发生 - 所以我将这个行为归结为关于流的PHP实现的一些模糊细节。

3 个答案:

答案 0 :(得分:1)

您可以使用wireshark或其他嗅探器来跟踪tcp-ip流量。通过这种方式,您可以查看问题是否与低级别问题(重新传输,数据包丢失等)有关。

答案 1 :(得分:1)

200ms听起来像是一个调度时间量。

为了确保您选择使用NULL或非零超时?您是在写入仅准备读取的套接字,反之亦然?您是否在再次调用select之前处理每个选择返回的fd?看到一些代码会很高兴......

如果您正在测试localhost,我认为它不会是网络。但是,如果有一些TCP重传(200ms是一个相当现代的Linux中最小的TCP重传超时),它看起来很像你所看到的。

答案 2 :(得分:0)

由于99%的请求仅在4毫秒内完成,这往往会影响一次性成本,例如DNS查找或从磁盘交换大量代码。