我正在通过环回 (127.0.0.1) 在 Linux 上使用优化的 Java NIO 选择器进行一些基准测试。
我的测试很简单:
- 一个程序将 UDP 数据包发送到另一个程序,该程序将其回显给发送者,并计算往返时间。下一个数据包仅在前一个数据包被确认(返回时)时发送。在执行基准测试之前,会使用数百万条消息进行适当的预热。该消息有 13 个字节(不包括 UDP 标头)。
对于往返时间,我得到以下结果:
- 最短时间:13 微
- 平均时间:19 微
- 75% 百分位数:18,567 毫微
- 90% 百分位数:18,789 毫微
- 99% 百分位数:19,184 毫微
- 99.9% 百分位数:19,264 毫微
- 99.99% 百分位数:19,310 毫微
- 99.999% 百分位数:19,322 毫微
但这里的问题是我正在旋转 100 万条消息。
如果我只旋转 10 条消息,我会得到非常不同的结果:
- 最短时间:41 微
- 平均时间:160 微
- 75% 百分位:150,701 毫微
- 90% 百分位数:155,274 毫微
- 99% 百分位数:159,995 纳秒
- 99.9% 百分位数:159,995 毫微
- 99.99% 百分位数:159,995 毫微
- 99.999% 百分位数:159,995 纳秒
如果我错了,请纠正我,但我怀疑一旦我们让 NIO 选择器旋转,响应时间就会变得最佳。但是,如果我们发送消息之间的间隔足够大,我们就要付出唤醒选择器的代价。
如果我只发送一条消息,我会收到 150 到 250 微秒之间的不同时间。
所以我对社区的问题是:
1 - 对于此往返数据包测试,我的最短时间为 13 微秒,平均为 19 微秒。到目前为止,我似乎击败了ZeroMQ,所以我可能在这里遗漏了一些东西。从这个基准来看,ZeroMQ 在标准内核上的平均时间为 49 微秒(99% 百分位数)=> http://www.zeromq.org/results:rt-tests-v031
2 - 当我旋转一条或很少的消息时,我可以做些什么来改善选择器的反应时间?150微不好看。或者我应该假设在 prod 环境中选择器不会完全正确?
通过忙于在 selectNow() 周围旋转,我可以获得更好的结果。发送少量数据包仍然比发送很多数据包更糟糕,但我认为我现在达到了选择器性能限制。我的结果:
- 发送单个数据包我得到一致的 65 微秒往返时间。
- 发送两个数据包我平均得到大约 39 微秒的往返时间。
- 发送 10 个数据包,平均往返时间约为 17 微秒。
- 发送 10,000 个数据包,我平均获得大约 10,098 纳纳的往返时间。
- 发送 100 万个数据包,我平均获得 9,977 纳秒的往返时间。
结论
所以看起来 UDP 数据包往返的物理障碍平均为 10 微秒,尽管我有一些数据包在 8 微秒(最小时间)内完成了行程。
在忙碌的旋转中(感谢彼得),我能够从平均 200 微秒增加到单个数据包的平均 65 微秒。
不知道为什么 ZeroMQ比这慢 5 倍。(编辑:也许是因为我通过环回在同一台机器上测试这个并且ZeroMQ使用了两台不同的机器?)