Java: JIT method inlining - java

When does Java JIT inline a method call? Is it based on #times the caller method is called (if yes, what would that number be?), or some other criteria (and what would that be?)
I've read that JIT can inline 'final' methods, but it also inlines nonfinal methods based on runtime statistics, so want to know what is that triggering criteria.
I guess the answers would differ based on JVM implementation, but maybe there's something common across all of them?

The short answer is whenever it wants.
Very often a JITC will inline small final or pseudo-final methods automatically, without first gathering any stats. This is because it's easy to see that the inlining actually saves code bytes vs coding the call (or at least that it's nearly a "wash").
Inlining truly non-final methods is not usually done unless stats suggest it's worthwhile, since inlined non-finals must be "guarded" somehow in case an unexpected subclass comes through.
As to the number of times something may be called before it's JITCed or inlined, that's highly variable, and is likely to vary even within a running JVM.

the default inline threshold for a JVM running the server Hotspot compiler is 35 bytecodes.
Official docs

Typically JIT only inlines "small" methods by default. Other than that it's completely dependent on the implementation.

Related

Do private functions use more or less computer resources than public ones?

Computer resources being RAM, possessing power, and disk space. I am just curious, even though it is more or less by a tiny itty-bitty amount.
It could, in theory, be a hair faster in some cases. In practice, they're equally fast.
Non-static, non-public methods are invoked using the invokevirtual bytecode op. This opcode requires the JVM to dynamically look up the actual's method resolution: if you have a call that's statically compiled to AbstractList::contains, should that resolve to ArrayList::contains, or LinkedList::contains, etc? What's more, the compiler can't just reuse the result of this compilation for next time; what if the next time that myList.contains(val) gets called, it's on a different implementation? So, the compiler has to do at least some amount of checking, roughly per-invocation, for non-private methods.
Private methods can't be overridden, and they're invoked using invokespecial. This opcode is used for various kind of method calls that you can resolve just once, and then never change: constructors, call to super methods, etc. For instance, if I'm in ArrayList::add and I call super.add(value) (which doesn't happen there, but let's pretend it did), then the compiler can know for sure that this refers to AbstractList::add, since a class's super class can't ever change.
So, in very rough terms, an invokevirtual call requires resolving the method and then invoking it, while an invokespecial call doesn't require resolving the method (after the first time it's called -- you have to resolve everything at least once!).
This is covered in the JVM spec, section 5.4.3:
Resolution of the symbolic reference of one occurrence of an invokedynamic instruction does not imply that the same symbolic reference is considered resolved for any other invokedynamic instruction.
For all other instructions above, resolution of the symbolic reference of one occurrence of an instruction does imply that the same symbolic reference is considered resolved for any other non-invokedynamic instruction.
(empahsis in original)
Okay, now for the "but you won't notice the difference" part. The JVM is heavily optimized for virtual calls. It can do things like detecting that a certain site always sees an ArrayList specifically, and so "staticify" the List::add call to actually be ArrayList::add. To do this, it needs to verify that the incoming object really is the expected ArrayList, but that's very cheap; and if some earlier method call has already done that work in this method, it doesn't need to happen again. This is called a monomorphic call site: even though the code is technically polymorphic, in practice the list only has one form.
The JVM optimizes monomorphic call sites, and even bimorphic call sites (for instance, the list is always an ArrayList or a LinkedList, never anything else). Once it sees three forms, it has to use a full polymorphic dispatch, which is slower. But then again, at that point you're comparing apples to oranges: a non-private, polymorphic call to a private call that's monomorphic by definition. It's more fair to compare the two kinds of monomorphic calls (virtual and private), and in that case you'll probably find that the difference is minuscule, if it's even detectible.
I just did a quick JMH benchmark to compare (a) accessing a field directly, (b) accessing it via a public getter and (c) accessing it via a private getter. All three took the same amount of time. Of course, uber-micro benchmarks are very hard to get right, because the JIT can do such wonderful things with optimizations. Then again, that's kind of the point: The JIT does such wonderful things with optimizations that public and private methods are just as fast.
Do private functions use more or less computer resources than public ones?
No. The JVM uses the same resources regardless of the access modifier on individual fields or methods.
But, there is a far better reason to prefer private (or protected) beside resource utilization; namely encapsulation. Also, I highly recommend you read The Developer Insight Series: Part 1 - Write Dumb Code.
I am just curious, even though it is more or less by a tiny itty-bitty amount.
While it is good to be curious ... if you start taking this kind of thing into account when you are programming, then:
you are liable to waste a lot of time looking for micro-optimizations that are not needed,
your code is liable to be unmaintainable because you are sacrificing good design principles, and
you even risk making your code less efficient* than it would be if you didn't optimize.
* - It it can go like this. 1) You spend a lot of time tweaking your code to run fast on your test platform. 2) When you run on the production platform, you find that the hardware gives you different performance characteristics. 3) You upgrade the Java installation, and the new JVM's JIT compiler optimizes your code differently, or it has a bunch of new optimizations that are inhibited by your tweaks. 4) When you run your code on real-world workloads, you discover that the assumption that were the basis for your tweaking are invalid.

Do modern Java compilers/JVM inline functions/methods which are called exactly from one place?

I found out that the C++ compiler does so but I want to know if the Java compiler does the same since in that answer they said adding static would do so but static is different in java and C++. In my case performance would matter since am using functions that are called only once per frame in a game loop and called nowhere else, to make it more readable
In my code I have it setup up similar to this, except with many more calls
while(running)
{
update();
sync();
}
and then update(), render() would call more methods that call other methods
private final void update()
{
switch(gameState)
{
case 0:
updateMainMenu();
renderMainMenu();
break;
case 1:
updateInGame();
renderInGame();
break;
//and so on
}
}
private final void updateInGame()
{
updatePlayerData();
updateDayCycle();
//and so on
}
private final void updatePlayerData()
{
updateLocation();
updateHealth();
//and so on
}
So would the compiler inline these functions since they are only used once per frame in the same location?
If this is a bad question, plz tell me and I will remove it.
A Java JITC will attempt to inline any functions that appear (based on runtime statistics) to be called often enough to merit it. It doesn't matter whether the function is called in only one place or dozens of places -- each calling site is analyzed separately.
Note that the decision is based on several factors. How big the method is is one -- if there are a lot of potential inlining candidates only the most profitable will be inlined, to avoid "code bloat". But the frequency of the call (multiplied by the perceived expense of the call) is the biggest "score" factor.
One thing that will discourage inlining is obvious polymorphic calls. If a call might be polymorphic it must be "guarded" by code that will execute the original call if the arriving class is not the expected one. If statistics prove that a call is frequently polymorphic (and including all the polymorphic variants is not worthwhile) then it's likely not sufficiently profitable to inline. A static or final method is the most attractive, since it requires no guard.
Another thing that can discourage inlining (and a lot of other stuff) is, oddly enough, a failure to return from the method. If you have a method that's entered and then loops 10 million times internally without returning, the JITC never gets a chance to "swap out" the interpreted method and "swap in" the compiled one. But JITCs overcome this to a degree by using techniques for compiling only part of a method, leaving the rest interpreted.
For future reference, you can view the bytecode of a .class file with javap -c MyClass to see what your compiled code looks like.
To answer your question: the Java compiler does not inline methods. The JVM, on the other hand, analyzes your code and will inline at runtime if necessary. Basically, you shouldn't worry about it -- leave it to the JVM, and it will inline if it finds it beneficial. The JVM is typically smarter than you when it comes to these things.
From http://www.oracle.com/technetwork/java/whitepaper-135217.html#method:
Method Inlining
The frequency of virtual method invocations in the Java programming language is an important optimization bottleneck. Once the Java HotSpot adaptive optimizer has gathered information during execution about program hot spots, it not only compiles the hot spot into native code, but also performs extensive method inlining on that code.
Inlining has important benefits. It dramatically reduces the dynamic frequency of method invocations, which saves the time needed to perform those method invocations. But even more importantly, inlining produces much larger blocks of code for the optimizer to work on. This creates a situation that significantly increases the effectiveness of traditional compiler optimizations, overcoming a major obstacle to increased Java programming language performance.
Inlining is synergistic with other code optimizations, because it makes them more effective. As the Java HotSpot compiler matures, the ability to operate on large, inlined blocks of code will open the door to a host of even more advanced optimizations in the future.

How to ensure the methods are not inlined by the java compiler?

For testing purposes I need to be sure that certain methods are not inlined when the respective code is compiled to produce the .class files.
How do I do it in Eclipse?
EDIT
For those who really need to know why, before they tell how, here is the explanation - I am testing a code, which examines and manipulates JVM byte code. This is why I want sometimes to avoid method inlining.
You don't; you have very little control over how the compiler and JIT optimize bytecode.
It's not clear to me why you'd want to do this, though.
Note that various JVM implementations may allow tweaking, e.q., -XX:MaxInlineSize= in HotSpot might be set to an impossibly-low number meaning no methods would be inlined. There may be an equivalent option in the Eclipse compiler, but I'd be wary.
Java methods are never inlined when producing the .class files (only by an optimizing JVM at run time), so you have nothing to worry about.
When it comes to Java inlining functions, you are entirely at the whim of the compiler. You have no say in it whatsoever.
There are some various metrics that it uses to determine if something should be inlined. I believe one of these is the number of bytecode instructions in the method. So if you had a method like this:
void foo() {
if(SOME_GLOBAL_BOOLEAN_THATS_ALWAYS_FALSE) {
// lots of statements here
}
// code here
}
You might be able to reduce the chance of it inlining on you, provided you were clever enough in your if statement to make sure it wasn't going to optimize it out on you.

Java optimizations: (Hotspot/Dalvik) Optimization of final method returning a constant?

Can anyone tell me if either Hotspot or Dalvik is smart enough to inline calls to a final method returning a constant (static final) int value? Ideally the method call would be replaced by the constant. This might either be at class load time or through JIT.
This has implications in the design of some code I'm working on.
I would think that the answer is "no, optimization will not happen because of absence or presence of the final keyword", at least on the HotSpot VM. But optimization will likely happen because of other factors.
Here's what Brian Goetz says in this article (sorry for the long quote):
Like many myths about Java performance, the erroneous belief that
declaring classes or methods as final results in better performance is
widely held but rarely examined. The argument goes that declaring a
method or class as final means that the compiler can inline method
calls more aggressively, because it knows that at run time this is
definitely the version of the method that's going to be called. But
this is simply not true. Just because class X is compiled against
final class Y doesn't mean that the same version of class Y will be
loaded at run time. So the compiler cannot inline such cross-class
method calls safely, final or not. Only if a method is private can the
compiler inline it freely, and in that case, the final keyword would
be redundant.
On the other hand, the run-time environment and JIT compiler have more
information about what classes are actually loaded, and can make much
better optimization decisions than the compiler can. If the run-time
environment knows that no classes are loaded that extend Y, then it
can safely inline calls to methods of Y, regardless of whether Y is
final (as long as it can invalidate such JIT-compiled code if a
subclass of Y is later loaded). So the reality is that while final
might be a useful hint to a dumb run-time optimizer that doesn't
perform any global dependency analysis, its use doesn't actually
enable very many compile-time optimizations, and is not needed by a
smart JIT to perform run-time optimizations.
There's also a good post why final is not final any more, at least in Java 5.
Inlining is something the JIT compiler might do if it detects a hot spot, a method in the byte code that has been called that often that it probably worth spending some CPU time on compiling the byte code into machine code.
There's a very good chance that the JIT compiler will inline a final method (as it can't be overwritten). And chances will be even better if that method just returns a constant value.
But it's my understanding - if the calling method is not a hot spot, then it will not be compiled and there'll be no inlining of the final methods.
(Information source in german language)
Alternatively, Soot is expected to optimize Java bytecode for such case.

Why all java methods are implicitly overridable?

In C++, I have to explicitly specify 'virtual' keyword to make a member function 'overridable', as there involves an overhead of creating virtual tables and vpointers, when a member function is made overridable (so every member function is implicitly not overridable for performance reasons).
It also allows a member function to be hidden (if not overridden) when a subclass provides a separate implementation with the same name and signature.
The same technique is used in C# as well. I am wondering why Java waved away from this behavior and made every method overridable by default and provided the ability to disable overriding behavior on explicit use of 'final' keyword.
The better question might be "Why does C# have non-virtual methods?" Or at the very least, why aren't they virtual by default with the option to flag them as non-virtual?
In C++, there is the idea (as Brian so nicely pointed out) that if you don't want it, you don't pay for it. The problem is that if you do want it, this usually means you end up paying through the nose for it. In most Java implementations, they are designed explicitly for lots of virtual calls; the vtable implementations tend to be fast, scarcely more expensive than non-virtual calls, meaning the primary advantage of non-virtual functions is lost. Furthermore, JIT compilers can inline virtual functions at runtime. As such, for efficiency reasons, there is very little reason actually to use non-virtual functions.
Thus, it largely comes down to the principle of least surprise. It tells us that all methods to behave the same way, not half of them being virtual and half of them being non-virtual. Since we need to have at least some virtual methods to achieve this polymorphism thing, it makes sense to have them all be virtual. Furthermore, having two methods with the same signature is just asking to shoot yourself in the foot.
Polymorphism also dictates that the object itself should have control over what it does. It's behavior should not be determinate on whether the client thinks it's a FooParent or a FooChild.
EDIT: So I'm being called on my assertions. This next paragraph is conjecture on my part, not a statement of fact.
An interesting side effect of all this is that Java programmers tend to use interfaces very heavily. Since the virtual method optimizations make the cost of interfaces essentially non-existent, they allow you to use a List (for example) instead of an ArrayList, and switch it out for a LinkedList at some later date with a simple one-line change and no additional penalty.
EDIT: I'll also pony up a couple sources. While not the original sources, they do come from Sun explaining some of the workings on HotSpot.
Inlining
VTable
Taken from here (#34)
There’s no virtual keyword in Java
because all non-static methods always
use dynamic binding. In Java, the
programmer doesn’t have to decide
whether to use dynamic binding. The
reason virtual exists in C++ is so you
can leave it off for a slight increase
in efficiency when you’re tuning for
performance (or, put another way, "If
you don’t use it, you don’t pay for
it"), which often results in confusion
and unpleasant surprises. The final
keyword provides some latitude for
efficiency tuning – it tells the
compiler that this method cannot be
overridden, and thus that it may be
statically bound (and made inline,
thus using the equivalent of a C++
non-virtual call). These optimizations
are up to the compiler.
A bit circular, perhaps.
So Java's rationale is probably something like this: the whole point of an object-oriented language is that things can be extended. So in terms of pure design, it really makes little sense to treat extensible as the "special case".
Remember that Java has the luxury of compiling at runtime. So some of the performance arguments in C++ compilation go out the window. In C++, if a class might be overridden, then the compiler has to take extra steps. In Java, there's no mystery about it: at any given moment in time, the JVM knows whether or not a particular method/class has been overridden or not, and that's essentially what counts.
Note that the final keyword is essentially about program design, not optimisation. The JVM doesn't need this information to see whether or not a class/method has been overridden!!
If the question is about to ask what is the better approach between java and C++/C# then it was already discussed in opposite direction in another thread, and many resource available on the net
Why C# implements methods as non-virtual by default?
http://www.artima.com/intv/nonvirtual.html
Recent introduction of #Override annotation and its wide adoption in new code, suggest that the exact answer to the question "Why all java methods are implicitly overridable?" is indeed because the designer made a mistake. (And they already fixed it)
Oh ! I'm going to get negative vote for this.
Java tries to move closer to a more dynamic language definition, where everything is an object and everything is a virtual method. It also wants to avoid ambiguity and hard to understand constructs, which it's designers viewed as a flaw in C++, therefore no operator overloading, and in this case no ability to have two public method signatures on one class hierarchy invoking different methods depending on the type of the variable referencing it.
C# is more concerned about the stability of subclasses and making sure that the subclasses behave predictably. C++ is concerned about performance.
Three different design priorities, leading to different choices.
I would say that in Java cost of virtual method is low compared to whole VM costs. In C++ it is significant cost, compared to assembly-like C background. Nobody would decide to make all methods called through pointer by default as result of C to C++ migration. It's too big change.

Categories