简体   繁体   English

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

[英]What is the overhead of a method call in a good Java VM?

Can someone come up with a disassembled machine code assembler listing? 有人能想出一个反汇编的机器码汇编列表吗?

I mean there must be some overhead compared to the normal function call in C. 我的意思是与C中的普通函数调用相比,必须有一些开销。

The VM needs to track calls to find hotspots and when it uses compiled code it needs to provid ways to change the compiled method on fly if a new loaded class requires a recompilation. VM需要跟踪调用以查找热点,并且当它使用已编译的代码时,如果新加载的类需要重新编译,则需要提供更改已编译方法的方法。

I guess there is also a return stack overflow check somewhere. 我想在某处还有一个返回堆栈溢出检查。

EDIT: I think i should mention that i'm not a java programmer but a compiler writer and want to find out why java applications are so slow while the java micro benchmarks are comparable to native compiled code. 编辑:我想我应该提一下,我不是一个java程序员,而是一个编译器编写者,想要找出为什么java应用程序如此缓慢,而java微基准测试与本机编译代码相当。 So looking at some the details is important for me here, even if they take only a few dozend nanoseconds and a few additional instructions. 因此,在这里查看一些细节对我来说很重要,即使它们只需要几个几纳秒和一些额外的指令。

Java doesn't compile directly to machine code, it compiles to bytecode which is then either interpreted or compiled to machine code at runtime--I have no idea how to get to the machine code at runtime, I just imagine it as this huge mass of shifting, changing bytes that just ends up executing DAMN quickly and reliably. Java不直接编译为机器代码,它编译为字节码,然后在运行时解释或编译为机器代码 - 我不知道如何在运行时获取机器代码,我只是想象它作为这个巨大的质量移位,改变字节,最终快速可靠地执行DAMN。

A small method call should compile out completely at runtime. 一个小方法调用应该在运行时完全编译。 Even a large method call can be written as in-line machine code by the VM if enough references can be resolved or ignored. 如果可以解析或忽略足够的引用,即使是大型方法调用也可以由VM编写为内联机器代码。

Using Final can help a lot because it gives the VM hints as to how it might optimize even more. 使用Final可以提供很多帮助,因为它可以为VM提供关于如何进一步优化的提示。

Since a method call can actually compile out completely and at best has a minimal cost anyway--you really shouldn't worry about it. 因为方法调用实际上可以完全编译出来,并且最多只需要最小的成本 - 你真的不应该担心它。 Just code your best and worry about performance problems when you have a failing performance spec (at which point spot-optimizing will do MUCH better than trying to eliminate method calls across your code, ruining your codebase for everyone involved). 当你有一个失败的性能规范时,只需编写最好的代码并担心性能问题(在这一点上,优化点比尝试消除代码中的方法调用要好得多,破坏了所涉及的每个人的代码库)。

Note that because of the runtime analysis, it can actually be faster in some very rare cases than similar code in C (The c compiler won't profile at runtime and hand-optimize your code for you, you have to do all that yourself). 请注意,由于运行时分析,它在某些非常罕见的情况下实际上比C中的类似代码更快(c编译器不会在运行时进行分析并为您手动优化代码,您必须自己完成所有这些) 。

In the updated question, the OP wrote this: 在更新的问题中,OP写道:

I think i should mention that i'm not a java programmer but a compiler writer and want to find out why java applications are so slow while the java micro benchmarks are comparable to native compiled code. 我想我应该提一下,我不是一个java程序员,而是一个编译器编写器,想要找出为什么java应用程序如此慢,而java微基准测试与本机编译代码相当。

Then in a comment the OP wrote this: 然后在评论中,OP写道:

... i found that method calls in Java 1.3 SUN VM (the last i ever used) were extremely expensive almost doubling the speed as inlining was obviously working far far from perfect. ...我发现Java 1.3中的方法调用SUN VM(我用过的最后一个)非常昂贵,速度几乎加倍,因为内联显然远远不能完美。

I think that the real problem is that your view that "Java is slow" is based on experiences with a really old release of Java. 我认为真正的问题是你的观点“Java很慢”是基于Java 版本的经验。 The java JIT compilers have improved significantly in the 9 years since Java 1.3 was released. 自Java 1.3发布以来,Java JIT编译器在9年中得到了显着改进。

So looking at some the details is important for me here, even if they take only a few dozend nanoseconds and a few additional instructions. 因此,在这里查看一些细节对我来说很重要,即使它们只需要几个几纳秒和一些额外的指令。

If you are (by your own admission) a not a java programmer, but a (non-Java I assume) compiler writer, why are these details important to you? 如果你(自己承认)不是一个java程序员,而是一个(非Java我假设的)编译器编写器,为什么这些细节对你很重要?

UPDATE: I found this page on the Sun Wikis that may help. 更新:我发现太阳维基上的这个页面可能有所帮助。 It applies to Java 7 which is only available as development builds, but there may be enough clues to help you disassemble JIT compiled code for current Java releases. 它适用于仅作为开发版本可用的Java 7,但可能有足够的线索来帮助您为当前Java版本反汇编JIT编译代码。

Well i never programmed Java since 1.3, but i'm using Eclipse, Netbeans and IntelliJ frequently and all of them are so slow compared to native GUI programs. 好吧,我从来没有编程过Java 1.3,但我经常使用Eclipse,Netbeans和IntelliJ,而且与本机GUI程序相比,它们都很慢。

I'm not sure that I'm clear on even how to generate statistics for the performance of a GUI--do you measure the time taken to perform a specific task, use automated testing, or is this one of those situations where you sort of eyeball it and say "it's slower/faster than program X". 我不确定我是否清楚如何生成GUI性能的统计数据 - 您是否测量执行特定任务所花费的时间,使用自动化测试,或者这是您排序的情况之一眼球它并说“它比程序X慢或快”。 I'm no expert on native GUI programs, but I do know that GUIs in Java often appear slow not because Java itself is necessarily slow, but because the GUI writers failed to construct a responsive GUI--putting long-running tasks on the Event Dispatch Thread, to name one example. 我不是本机GUI程序的专家,但我知道Java中的GUI经常看起来很慢,不是因为Java本身必然很慢,而是因为GUI编写者无法构建响应式GUI - 将长时间运行的任务放在事件上Dispatch Thread,举个例子。 In the absence of well-constructed comparison tests, it's hard to tell what's the fault of Java and what's the fault of bad GUI programming. 在缺乏构造良好的比较测试的情况下,很难说出Java的错误是什么,以及错误的GUI编程的错误是什么。

To answer your question, though, Bill K mentioned the Computer Programming Shootout Game as a source of numerous compiler benchmarks. 但是,为了回答你的问题,比尔K提到了计算机编程枪战游戏作为众多编译器基准的来源。 Another interesting source of statistics for Win32 platforms can be found here . 可以在此处找到Win32平台的另一个有趣的统计数据来源。

This is heavily dependent on the JVM you are using (especially when using one capable of just-in-time compiling to native code), since the optimizations performed over your code will ultimately determine this. 这在很大程度上取决于您使用的JVM(特别是在使用能够及时编译为本机代码的JVM时),因为对代码执行的优化最终将决定这一点。

For instance, the JVM may decide to inline your method, and then you do not have calling overhead at all. 例如,JVM可能决定内联您的方法,然后您根本没有调用开销。 If the method is not inlined, but still compiled into native code, you have an equivalent overhead to calling a method/function using a pointer in C/C++, plus the machine-specific requirements (for instance, setting up stack stace, arguments, epilogue/prologue). 如果方法没有内联,但仍然编译成本机代码,那么使用C / C ++中的指针调用方法/函数,加上特定于机器的要求(例如,设置堆栈stace,参数,结语/序幕)。 This should sum up to about the time to execute 10 to 30 native instructions, but it is an approximation---you should measure this if really important. 这应该总结一下执行10到30个本机指令的时间,但它是一个近似值 - 如果真的很重要,你应该测量它。

Figures should be very different if you are using a interpreting-only JVM, possibly with much higher overhead (never checked it myself, but if I had to guess, I'd bet on one extra magnitude---so around 100 to 300 instructions). 如果您使用仅解释JVM,数字应该是非常不同的,可能具有更高的开销(从未自己检查过,但如果我不得不猜测,我会打赌一个额外的数量---所以大约100到300个指令)。

The point here is that you are comparing apples and oranges. 这里的要点是你要比较苹果和橘子。 Java compiles at runtime (have you heard of JIT?), so it's not exactly comparable to C which compiles offline. Java在运行时编译(你听说过JIT吗?),所以它与离线编译的C不完全相同。 Most of the overhead comes from the time which you don't count in C (the compilation process) and not from the "method call" as you suppose 大部分开销来自你不计入C(编译过程)的时间,而不是你想象的“方法调用”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM