JVM方法调用和远程调用之间的性能差异是什么?

6

我正在收集有关JVM方法调用和使用二进制协议(换句话说,不是SOAP)进行远程方法调用之间性能差异的数据。我正在开发一个框架,在该框架中,方法调用可以由框架自行决定是本地还是远程执行,并且我想知道在什么时候评估远程方法调用是“值得”的,无论是在更快的服务器上还是在某种计算网格上执行。我知道远程调用会慢得多,因此我主要想了解数量级差异。它比本地调用慢10倍、100倍还是1,000倍?有人有这方面的数据吗?如果必要,我将编写自己的基准测试,但我希望能够重用一些现有的知识。谢谢!


1
我已经不理解那个将此标记为“不是一个真正的问题”的人了...但是那个将此标记为“不具建设性”的人应该前往最近的疯人院;) 感谢原帖作者提出这个酷问题,也感谢Peter Lawrey像往常一样给出了他的精彩答案。 - SyntaxT3rr0r
@SyntaxT3rr0r,出于duffymo和mikera所述的原因,这不是一个真正的问题。什么远程方法?通过什么网络?使用什么大小的参数?本地和远程之间的差异在远程方法执行时间越长时渐近为零。 - user207421
3个回答

4

开发了一个低延迟的RMI(最小约20微秒),但仍比直接调用慢1000倍。如果使用普通的Java RMI(最小约500微秒),则可能慢25000倍。

注意:这只是一个非常粗略的估计,旨在让您大致了解可能会看到的差异。有许多复杂因素可能会极大地改变这些数字。根据方法执行的内容,差异可能会较小,特别是如果将RMI执行到同一进程中,如果网络相对较慢,则差异可能会更大。

此外,即使存在非常大的相对差异,它可能对整个应用程序的影响并不大。


针对我上一条评论进行详细说明...

假设您有一个GUI需要每秒轮询一些数据,并使用后台线程来执行此操作。假设使用RMI需要50毫秒,而另一种选择是直接调用本地分布式缓存的副本,只需0.0005毫秒。这似乎是一个巨大的差异,达到了100,000倍。然而,RMI调用可以提前50毫秒开始轮询,仍然每秒轮询一次,用户几乎感觉不到差异。

更重要的是,当RMI与其他方法相比较时,如果它是适合工作的正确工具,则可能更简单。

使用JMS是使用RMI的替代方案。哪种方法最好取决于您的情况。


这是一个过于笼统的概括。请看我在原帖下面的评论。 - user207421
@EJP,有时候拥有一些想法总比没有想法好。然而,缺乏上下文的少量知识可能是危险的。数字值得加上大大的警告。 - Peter Lawrey

3

精确回答你的问题是不可能的。执行时间比例取决于以下因素:

  • 需要序列化进行远程调用的参数和返回值的大小/复杂度。
  • 方法本身的执行时间
  • 网络连接的带宽/延迟

但总的来说,直接的JVM方法调用非常快,任何与RMI引起的序列化和网络延迟相关的操作都会增加显著的开销。查看这些数字,以便给您提供大致的开销估算:

http://surana.wordpress.com/2009/01/01/numbers-everyone-should-know/

除此之外,您需要进行基准测试。
一条建议 - 确保您使用真正优秀的二进制序列化库(如avro、protocol buffers、kryo等),并与体面的通信框架(例如Netty)配对。这些工具比标准Java序列化/io设施要好得多,并且可能比您在合理时间内编写的任何内容都要好。

3
没有人能告诉你答案,因为决定是否分发不是关于速度的问题。如果是,你将永远不会进行分布式调用,因为它总是比在内存中进行相同的调用要慢。
你分发组件以便多个客户端可以共享它们。如果共享很重要,那么它的价值就超过了速度损失。
你的收支平衡点与方法调用速度无关,而与共享功能的价值有关。

你提出了一个很好的观点。然而,远程调用有一个优点,它引入了一个新的执行线程,可以并行运行当前线程,因此当前线程可以继续进行 -- 可能调用更多的远程调用 - 然后稍后汇总结果。使用本地线程也可能做到这一点,但可用线程的数量很快就会耗尽。但我确实同意,单个线程的执行将始终受到远程调用的影响;只有在我们并行运行大量任务时才有意义。 - Willis Blackburn
如果调用是异步的话,就可以实现;但如果它是同步的话就不行。如果应用程序进行调用并阻塞,那么它也无法继续前进了。还有一个问题是如何找出进程是否完成以及如何获取结果。我不同意你关于本地线程的观点;在本地仍然有异步选项。我认为这条评论中没有任何正确的观点。 - duffymo
您可以在本地JVM中异步调用方法,但本地计算机上可用的核心数目比可能运行该方法的远程主机数目要少得多。 - Willis Blackburn
你仍然可以在一个核心上进行多个调用;在这种情况下,你只是进行时间片切换。潜在的数百个远程主机?是的。但实际上并不会有那么多。 - duffymo
假设每个方法都是CPU绑定的,那么启动超过核心数的并行方法调用是没有意义的。是的,它们会进行时间片切换,但由于存在更多的上下文切换和管理开销,工作总体上将需要更长的时间。至于数百个远程主机,在我们公司,拥有数百个主机池来运行计算是非常普遍的。所以我不知道你所说的“实际上不可能”。看起来你只是想找出我写的每件事情的问题,这很奇怪,因为我基本上同意你的最初答案。 - Willis Blackburn
Swing事件线程的存在表明你是错误的。长时间运行的进程确实有意义,可以分配给现有的线程,因为它允许用户继续操作并使UI体验更加响应。 - duffymo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接