jjzjj

Java NIO 选择器可能的最小延迟

coder 2024-03-08 原文

我正在通过环回 (127.0.0.1) 在 Linux 上使用优化的 Java NIO 选择器进行一些基准测试。

我的测试很简单:

  • 一个程序将一个 UDP 数据包发送到另一个程序,另一个程序将其回显给发送者并计算往返时间。下一个数据包仅在前一个数据包被确认(返回时)时才发送。在执行基准测试之前,会使用几百万条消息进行适当的预热。消息有 13 个字节(不包括 UDP header )。

对于往返时间,我得到以下结果:

  • 最短时间: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 - 当我旋转单个或很少的消息时,我可以做些什么来改善选择器的 react 时间? 150 micros 看起来不太好。或者我应该假设在产品环境中选择器不会完全正确?


通过忙着围绕 selectNow() 旋转,我可以获得更好的结果。发送少量数据包仍然比发送许多数据包更糟糕,但我认为我现在达到了选择器性能极限。我的结果:

  • 发送单个数据包时,我得到了一致的 65 微秒往返时间。
  • 发送两个数据包平均往返时间约为 39 微秒。
  • 发送 10 个数据包平均需要大约 17 微秒的往返时间。
  • 发送 10,000 个数据包,平均往返时间约为 10,098 纳秒。
  • 发送 100 万个数据包平均需要 9,977 纳秒的往返时间。

结论

  • 所以看起来 UDP 数据包往返的物理屏障平均为 10 微秒,尽管我有一些数据包在 8 微秒(最短时间)内完成了一次传输。

  • 通过繁忙的旋转(感谢 Peter),我能够将单个数据包的平均 200 微增至一致的平均 65 微。

  • 不确定为什么 ZeroMQ 是 5 times slower比起那个来说。 (编辑:可能是因为我在同一台机器上通过环回测试这个,而 ZeroMQ 使用的是两台不同的机器?)

最佳答案

你经常看到唤醒线程的情况可能非常昂贵,不仅仅是因为线程唤醒需要时间,而且线程运行速度慢了 2-5 倍,因为缓存和

我过去避免这种情况的方法是忙等待。不幸的是,即使它是一个空集合,每次调用它时 selectNow 都会创建一个新集合。这会产生如此多的垃圾,不值得使用。

绕过它的一种方法是忙于等待非阻塞套接字。这并不能很好地扩展,但可以为您提供最低的延迟,因为线程不需要唤醒,并且您在此之后运行的代码更有可能位于缓存中。如果您也使用线程亲和性,它可以减少您的线程干扰。

我还建议尽量减少代码锁定和垃圾。如果你这样做,你可以在 Java 中有一个进程,它在 90% 的时间内在 100 微秒内发送对传入数据包的响应。这将允许您在每个数据包到达时以 100 Mb 的速度处理它们(由于带宽限制,最多间隔 145 微秒)对于 1 Gb 的连接,您可以非常接近。


如果你想在 Java 的同一个盒子上进行快速进程间通信,你可以考虑像 https://github.com/peter-lawrey/Java-Chronicle 这样的东西。这使用共享内存传递消息,往返延迟(使用套接字更难有效地做到这一点)小于 200 纳秒。它还会保留数据,如果您只是想要一种快速生成日志文件的方法,它会很有用。

关于Java NIO 选择器可能的最小延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12099446/

有关Java NIO 选择器可能的最小延迟的更多相关文章

  1. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  2. ruby - Rails 3 的 RGB 颜色选择器 - 2

    状态:我正在构建一个应用程序,其中需要一个可供用户选择颜色的字段,该字段将包含RGB颜色代码字符串。我已经测试了一个看起来很漂亮但效果不佳的。它是“挑剔的颜色”,并托管在此存储库中:https://github.com/Astorsoft/picky-color.在这里我打开一个关于它的一些问题的问题。问题:请建议我在Rails3应用程序中使用一些颜色选择器。 最佳答案 也许页面上的列表jQueryUIDevelopment:ColorPicker为您提供开箱即用的产品。原因是jQuery现在包含在Rails3应用程序中,因此使用基

  3. ruby - 获取数组中的值并最小化某个类属性的最优雅的方法是什么? - 2

    假设我有以下类(class):classPersondefinitialize(name,age)@name=name@age=ageenddefget_agereturn@ageendend我有一组Person对象。是否有一种简洁的、类似于Ruby的方法来获取最小(或最大)年龄的人?如何根据它对它们进行排序? 最佳答案 这样做会:people_array.min_by(&:get_age)people_array.max_by(&:get_age)people_array.sort_by(&:get_age)

  4. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

  5. ruby-on-rails - 在所有延迟的作业之前 Hook - 2

    是否可以在所有delayed_job任务之前运行一个方法?基本上,我们试图确保每个运行delayed_job的服务器都有我们代码的最新实例,所以我们想运行一个方法来在每个作业运行之前检查它。(我们已经有了“check”方法并在别处使用它。问题只是关于如何从delayed_job中调用它。) 最佳答案 现在有一种官方方法可以通过插件来做到这一点。这篇博文通过示例清楚地描述了如何执行此操作http://www.salsify.com/blog/delayed-jobs-callbacks-and-hooks-in-rails(本文中描述

  6. ruby-on-rails - Rails 单选按钮 - 模型中多列的一种选择 - 2

    我希望用户从一个模型的三个选项中选择一个。即我有一个模型视频,可以被评为正面/负面/未知目前我有三列bool值(pos/neg/unknown)。这是处理这种情况的最佳方式吗?为此,表单应该是什么样的?目前我有类似的东西但显然它允许多项选择,而我试图将它限制为只有一个..怎么办? 最佳答案 如果要使用字符串列,让我们说rating。然后在你的表单中:#...#...它只允许一个选择编辑完全相同但使用radio_button_tag: 关于ruby-on-rails-Rails单选按钮-模

  7. ruby-on-rails - CarrierWave - PDF - 只选择第一页 - 2

    我的Rails应用程序中安装了carrierwave。但是,当用户上传多页pdf时,我只希望应用程序获取文档中的第一页并将其转换为jpeg。这可能吗?用什么命令?这是我的uploader。#encoding:utf-8classImageUploader[200,300]##defscale(width,height)##dosomething#end#Createdifferentversionsofyouruploadedfiles:version:thumbdoprocess:resize_to_fill=>[150,210]process:convert=>:jpgdefful

  8. ruby-on-rails - ActiveAdmin 自定义选择过滤器下拉名称 - 2

    对于用户模型,我有一个过滤器来检查用户的预订状态,该状态由整数值(0、1或2)表示。UserActiveAdmin索引页上的过滤器是通过以下代码实现的:filter:booking_status,as::select然而,这会导致下拉选项为0、1或2。当管理员用户从下拉列表中选择它们时,我更愿意自己将它们命名为“未完成”、“待定”和“已确认”之类的名称。有没有办法在不改变booking_status在模型中的表示方式的情况下做到这一点? 最佳答案 假设booking_status是模型中的枚举字段,您可以使用:过滤器:booking

  9. ruby-on-rails - 多次选择一个随机数,但绝不会两次选择相同的随机数 - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:HowdoIgeneratealistofnuniquerandomnumbersinRuby?我想做的事:Random.rand(0..10).timesdoputsRandom.rand(0..10)end但如果随机数已经显示过,则无法再次显示。如何最轻松地做到这一点?

  10. Ruby Regex,获取所有可能的匹配项(不截断字符串) - 2

    我遇到了ruby​​正则表达式的问题。我需要找到所有(可能重叠的)匹配项。这是问题的简化:#Simpleexample"Hey".scan(/../)=>["He"]#Actualresults#Withoverlappingmatchestheresultshouldbe=>["He"],["ey"]我尝试执行并获得所有结果的正则表达式如下所示:"aaaaaa".scan(/^(..+)\1+$/)#Thislooksformultiplesof(here)"a"biggerthanonethat"fills"theentirestring."aa"*3=>true,"aaa"*2=

随机推荐