优秀Java VM中方法调用的开销是多少?

时间:2009-12-02 01:46:33

标签: java performance jvm

有人能想出一个反汇编的机器码汇编程序列表吗?

我的意思是与C中的普通函数调用相比,必须有一些开销。

虚拟机需要跟踪调用以查找热点,当它使用已编译的代码时,如果新加载的类需要重新编译,则需要提供更改已编译方法的方法。

我想在某处还有一个返回堆栈溢出检查。

编辑:我想我应该提一下,我不是一个java程序员,而是一个编译器编写者,想要找出为什么java应用程序如此缓慢,而java微基准测试与本机编译代码相当。因此,在这里查看一些细节对我来说很重要,即使它们只需要几个几纳秒和一些额外的指令。

5 个答案:

答案 0 :(得分:6)

Java不直接编译为机器代码,它编译为字节码,然后在运行时将其解释或编译为机器代码 - 我不知道如何在运行时获取机器代码,我只想象它为这种巨大的移动,改变字节,最终快速可靠地执行DAMN。

一个小方法调用应该在运行时完全编译。如果可以解析或忽略足够的引用,即使是大型方法调用也可以由VM编写为内联机器代码。

使用Final可以提供很多帮助,因为它可以为VM提供关于如何进一步优化的提示。

由于方法调用实际上可以完全编译,并且最多只需要最小的成本 - 你真的不应该担心它。当你的性能指标失败时,只需编写最好的代码并担心性能问题(此时,优化点优于尝试消除代码中的方法调用,破坏相关人员的代码库)。

请注意,由于运行时分析,它在某些非常罕见的情况下实际上比C中的类似代码更快(c编译器不会在运行时进行分析并为您手动优化代码,您必须全部执行你自己)。

答案 1 :(得分:3)

在更新的问题中,OP写道:

  

我想我应该提到我不是   一个java程序员,但编译器   作家,想找出为什么java   应用程序是如此缓慢而   java微基准测试具有可比性   本地编译代码。

然后在评论中,OP写道:

  

...我发现方法调用了   Java 1.3 SUN VM(我用过的最后一个)   几乎是非常昂贵的   将内嵌速度提高一倍   显然工作距离很远   完美。

我认为真正的问题是你认为“Java很慢”是基于Java的非常古老的版本的经验。自Java 1.3发布以来,Java JIT编译器在9年中得到了显着改进。

  

所以看一些细节是   对我来说很重要,即使他们   只需要几个几秒纳秒   一些额外的说明。

如果您(自己承认)不是java程序员,而是(非Java我假设)编译器编写者,为什么这些细节对您很重要?

更新:我发现Sun Wikis上的this page可能有所帮助。它适用于仅作为开发版本提供的Java 7,但可能有足够的线索来帮助您为当前Java版本反汇编JIT编译代码。

答案 2 :(得分:1)

  

我从未编写过自1.3开始编写Java的程序,但我经常使用Eclipse,Netbeans和IntelliJ,而且与本机GUI程序相比,它们都非常慢。

我不确定我是否清楚如何生成GUI性能的统计数据 - 您是否测量执行特定任务所花费的时间,使用自动化测试,或者这是其中一种情况在那里你会注意它并说“它比程序X慢或快”。我不是本机GUI程序的专家,但我知道Java中的GUI经常看起来很慢,不是因为Java本身必然很慢,而是因为GUI编写者无法构建响应式GUI - 将长时间运行的任务放在事件上Dispatch Thread,举个例子。在缺乏构造良好的比较测试的情况下,很难说出Java的错误是什么,以及错误的GUI编程是什么错误。

为了回答你的问题,比尔K提到了计算机编程枪战游戏作为众多编译器基准测试的来源。可以找到另一个有趣的Win32平台统计数据来源here

答案 3 :(得分:0)

这在很大程度上取决于您正在使用的JVM(特别是在使用能够及时编译为本机代码的JVM时),因为对代码执行的优化最终将决定这一点。

例如,JVM可能决定内联您的方法,然后您根本没有调用开销。如果方法没有内联,但仍然编译成本机代码,那么使用C / C ++中的指针调用方法/函数,加上特定于机器的要求(例如,设置堆栈stace,参数,结语/序幕)。这应该总结一下执行10到30个本机指令的时间,但它是一个近似值 - 如果真的很重要,你应该测量它。

如果您使用仅解释JVM,数字应该是非常不同的,可能具有更高的开销(从未自己检查过,但如果我不得不猜测,我会赌一个额外的数量---所以大约100到300条指令)。

答案 4 :(得分:0)

这里的重点是你要比较苹果和橘子。 Java在运行时编译(你听说过JIT吗?),所以它与离线编译的C不完全相同。大部分开销来自您不计入C(编译过程)的时间,而不是您想象的“方法调用”