【问题标题】:How Fast Might RMI Be?RMI 可能有多快?
【发布时间】:2011-01-05 08:28:14
【问题描述】:

我已经看到了这个问题:Communication between two separate Java desktop applications(答案:JGroups),我正在考虑使用 JavaGroups 或直接 RMI 来实现一些东西,但速度至关重要。我不会发送大量数据(MIDI 消息的内容,因此每个 3 个字节,每三毫秒最多说两条消息),这将全部在同一台机器上。 认为同一台物理机上的 RMI/JGroups 会很慢是不是很愚蠢?

(我的想法是我无法承受超过 1 毫秒的延迟,因为我已经有了一些延迟,但我不确定在这种情况下如何最好地谈论速度。)

我想我真正的问题是:在 Java 中是否有比 TCP/IP 更快的应用程序间通信选项?我的意思是已经在 J​​ava 中实现的东西,而不是我的 JNI 可能性d需要实施:)

我知道,不要过早优化,但总比后悔好。

【问题讨论】:

  • 这里的愚蠢之处甚至是考虑 Socket.getOutputStream.write(byte[]) 以外的任何内容来处理由三个字节组成的数据你没有对象,也没有任何明显的 RPC 语义,所以没有理由甚至考虑其他任何事情。可能您应该考虑使用 UDP 多播。

标签: java performance rmi jgroups


【解决方案1】:

在 Java 中是否有比 TCP/IP 更快的应用程序间通信选项?

不显着...... AFAIK。

但我认为你的想法是错误的。假设您正在移动小消息,主要的性能杀手将是进行调用的开销,而不是移动字节的速度。这些开销包括进行系统调用、在客户端和服务器端切换进程上下文、在内核中处理消息包头和路由数据包所花费的时间。并且任何同步的类似 RPC 的交互都需要进行调用以等待回复;即应用程序 -> 服务器 -> 往返时间。

获得更大吞吐量的方法是关注以下方面:

  • 减少应用程序所需的 RPC 数量;例如通过将它们组合成更粗粒度,并且

  • 研究将同步交互转变为异步交互的方法;例如使用基于消息而不是基于 RPC 的技术。

【讨论】:

  • 谢谢斯蒂芬,我认为这是正确的,也是一个很好的答案。我实际上不会双向谈论:一个程序将使用另一个程序进入一个应用程序上下文(VST 主机,对编造的术语感到抱歉),它本身没有运行。此外,虽然在我的特殊情况下,只有一点点聚合是可能的(消息进来时需要),但我认为你对聚合和异步同步是正确的。
【解决方案2】:

如果速度至关重要,您应该在同一个线程中进行调用。使用网络你不会得到这么快。

但是,假设速度不是那么重要,您可以在大约 500 微秒内执行 Java RMI 调用,并且使用自定义编码的 RPC,您可以在大约 24 微秒内通过环回进行调用。即使在同一个 JVM 中的线程之间传递数据也可能需要 8 微秒。

您需要决定您愿意允许多少时间进行网络呼叫。您还需要确定开始调用的时间是关键时间还是返回结果的时间。 (通常后者的开销翻倍)

注意:我在这里说的是微秒,而不是毫秒。对于您的目的,我会忽略任何需要多毫秒的选项。

【讨论】:

  • 哇,不知道我当时是怎么错过这个答案的。所以 RMI 基本上是非常快的。
  • @Yar 都是相对的。 0.5 ms 可能已经足够快了,在这种情况下,RMI 可能是最佳选择。通过调整系统和 JVM,您可以通过回送套接字将往返延迟降低到 6 微秒,使用共享内存,您可以将其降低到 200 纳秒。
  • 诚然,这都是相对的,但是在用户与音乐程序交互的系统中添加一次这种延迟是完全可以的,假设它只是旋钮和按钮。即使对于鼓,只要延迟相对一致,我认为 25 微秒并不明显。
  • 对于人类来说,任何短于 1/50 秒 (20 毫秒) 的内容都不会引起注意。某些国家/地区的 TZ 屏幕更新频率为 50 Hz,而某些电影院的更新频率为 42 Hz,并且不明显。
  • @Peter Lawrey - 视觉连续性与音频成像非常不同。根据silcom.com/~aludwig/EARS.htm,低于 200Hz 的东西会导致明显的回声。不知道这个应用程序最终会产生什么,但音频准确性非常重要。
【解决方案3】:

This benchmark 大约有两年的历史,但它表明唯一比 RMI 更快的流行 Java 远程处理解决方案是Hessian 2(我相信它仍处于测试阶段)。

但是,如果您的消息只有一位数字节,那么使用任何远程解决方案似乎都过大了,尤其是如果进程位于同一台机器上。如果可能的话,我建议将它们合并到一个进程中。您也可以考虑只使用plain old Java sockets

【讨论】:

  • 绝对正确,plain-old-Java-sockets 可以做到。我仍然担心下面的堆栈(TCP/IP?)...如果让两个应用程序通过普通的旧 Java 套接字进行通信,它会给一个应用程序增加多少延迟?
  • 抱歉,没有提到:如果可以的话,我会将它们合并到一个进程中。但我不能,因为一个是独立应用,另一个是 VST 插件。
  • 我真的说不出使用套接字会增加多少延迟。这不会太多,但是当我们谈论这么小的时间单位时,我不能确切地说出期望有多少。使用某种共享内存模型进行通信应该更快,但我不确定如何在 JNI 之外做到这一点。这并不是说那里有一些东西可以工作。但是,如果您的应用程序容易受到延迟的影响,这似乎是一个设计缺陷。您可能需要考虑使用 java.nio 类的一些缓冲功能来帮助缓解这种情况。
  • 优秀的评论,感谢您的对话。我也猜它会非常快。现在不知道它是如何工作的,但在过去,EJB 容器与带有 RMI 的 servlet 容器通信,所以同一个盒子上的网络延迟应该不会太多。
【解决方案4】:

认为同一台物理机上的 RMI/JGroups 会很慢是不是很愚蠢?

如果您的机器不错,可能是的 :) 如果您在一台有大量进程占用 CPU 等的机器上运行,那么情况可能会有所不同。与往常一样,确定您是否会遇到与我相同的事情的最佳方法是对其进行测试。

以下是在同一 JVM 中使用 nanoTime 所花费的时间(以毫秒为单位) 使用 rmi 发送字符串“123”并在服务器上将其与“abc”连接以获取 "123abc" 并返回它。

冷 JVM:大约 0.25 毫秒延迟

0.250344
0.262695
0.241540
0.282461
0.301057
0.307938
0.282102

暖 JVM:大约 0.07 毫秒的延迟。

0.87916
0.72474
0.73399
0.64692
0.62488
0.59958
0.59814
0.66389

因此,如果 RMI 服务器和客户端在本地运行,您将在 1 毫秒内完成。

【讨论】:

    猜你喜欢
    • 2011-10-09
    • 2011-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-21
    • 1970-01-01
    相关资源
    最近更新 更多