I was curious, I see this kind of thing a lot:
Arrays.sort(array, new Comparator<Integer>() {
public int compare(Integer a, Integer b) {
return Math.abs(a) < Math.abs(b);
}
});
since the anonymous class created here has no instance variables, is the standard JDK compiler smart enough to only instantiate that anonymous class once and reuse it? Or is it advisable to instantiate that anonymous class in a static field and always pass the static Comparator object?
UPDATE: When I say "JDK compiler", I mean the JIT portion too. The above is also just an example. I was really curious if I should, as a best practice, create static fields for the above instead of inlining anonymous class instantiations. In some cases the performance/resource usage issue will be negligible. But other cases might not be...
javac will definitely not do such thing; that would violate the language semantics. JVM could optimize it in theory, but it's not that smart yet. A static one would be faster.
Ironically, such analysis and optimization would be easy for javac, and it can be done today, except it's forbidden to do so - the source says new, so javac must new.
Rumor has it that the coming lambda expression in java 8 will make an effort on this issue, in
Arrays.sort(array, (Integer a,Integer b) => Math.abs(a)<Math.abs(b) )
javac is required to analyze that the lambda is stateless, and a lazily created single instance is enough, and that's what it must compile the code into.
The answer is maybe.
javac will compile this into bytecode that is true to your code. Therefore, the class will be instantiate anew each time this code is called. However the JVM performs many sophisticated optimisations at runtime, and MIGHT - depending on many factors - perform some optimisations here.
In any case, unless you've noticed a real performance issue here, I'd recommend not trying to manually optimise.
You can use javap to check yourself; my suspicion is that it will create it on every call. Such optimizations are handled by hotspot but in this case since the anonymous only has methods (no fields to initialize) the overhead is very small.
The real question here is not what javac will do. As Steve McLeod says, javac will produce bytecode which matches your source code. The question is what hotspot will do at runtime. I imagine it will simple inline the whole lot (including the Math.abs() call).
The compiler does very little optimisation. The jit does most of it. It will optimise this code but it won't avoid creating Integer objects and unless you have an array of Integer this will be your bottle neck. So much so that any other optimisation it does won't matter.
Related
I have been pulled into a performance investigation of a code that is similar to the below:
private void someMethod(String id) {
boolean isHidden = someList.contains(id);
boolean isDisabled = this.checkIfDisabled(id);
if (isHidden && isDisabled) {
// Do something here
}
}
When I started investigating it, I was hoping that the compiled version would look like this:
private void someMethod(String id) {
if (someList.contains(id) && this.checkIfDisabled(id)) {
// Do something here
}
}
However, to my surprise, the compiled version looks exactly like the first one, with the local variables, which causes the method in isDisabled to always be called, and that's where the performance problem is in.
My solution was to inline it myself, so the method now short circuits at isHidden, but it left me wondering: Why isn't the Java Compiler smart enough in this case to inline these calls for me? Does it really need to have the local variables in place?
Thank you :)
First: the java compiler (javac) does almost no optimizations, that job is almost entirely done by the JVM itself at runtime.
Second: optimizations like that can only be done when there is no observable difference in behaviour of the optimized code vs. the un-optimized code.
Since we don't know (and the compiler presumably also doesn't know) if checkIfDisabled has any observable side-effects, it has to assume that it might. Therefore even when the return value of that method is known to not be needed, the call to the method can't be optimized away.
There is, however an option for this kind of optimization to be done at runtime: If the body (or bodies, due to polymorphism) of the checkIfDisabled method is simple enough then it's quite possible that the runtime can actually optimize away that code, if it recognizes that the calls never have a side-effect (but I don't know if any JVM actually does this specific kind of optimization).
But that optimization is only possible at a point where there is definite information about what checkIfDisabled does. And due to the dynamic class-loading nature of Java that basically means it's almost never during compile time.
Generally speaking, while some minor optimizations could possibly be done during compile time, the range of possible optimizations is much larger at runtime (due to the much increased amount of information about the code available), so the Java designers decided to put basically all optimization effort into the runtime part of the system.
The most-obvious solution to this problem is simply to rewrite the code something like this:
if (someList.contains(id)) {
if (this.checkIfDisabled(id)) {
// do something here
If, in your human estimation of the problem, one test is likely to mean that the other test does not need to be performed at all, then simply "write it that way."
Java compiler optimizations are tricky. Most optimizations are done at runtime by the JIT compiler. There are several levels of optimizations, the maximum number of optimizations by default will be made after 5000 method invocations. But it is rather problematic to see which optimizations are applied, since JIT compile the code directly into the platform's native code
In this article, I was surprised to read:
I always imagined that having a final method meant that the compiler would compile all calls to it using invokespecial instead of invokevirtual, to "devirtualize" the method calls since it already knows for sure at compile-time where to transfer execution. Doing this at compile time seems like a trivial optimization, while leaving this up to the JIT is far more complex. But no, the compiler doesn't do this. It's not even legal to do it!
Doing this at compile time seems like a trivial optimization, since it already knows for sure at compile-time where to transfer execution. What's the reason this doesn't happen?
Posting the answer that EJP pointed out in the comments:
Java has a separate compilation model, thus it forbids cross-file optimization (with a notable exception, compile-time constant inlining). What if you change the method to non-final, and do not recompile the clients? What if you do runtime bytecode replacement (search for "instrumentation")?
Side note: as an engineer, your expectations should be a function of the tool. This is not C++. Where you can afford an interpreter, bytecode optimization is premature optimization.
Keep your mind object-oriented. You ask the compiler to do it, let it decide the best behind the scenes; if a 20yo compiler does not do it, it's probably unimportant. -O is well documented (at least on Oracle's JDK) and it just inlines the private and static methods inside the file that declares them.
Edit 2:
Does a program with a fully object-oriented implementation give high performance? Most of the framework is written with full power of it. However, reflection is also heavily used to achieve it like for AOP and dependency injection. Use of reflection affects the performance to a certain extent.
So, Is it good practice to use reflection? Is there some alternative to reflection from programming language constructs? To what extent should reflection be used?
Reflection is, in itself and by nature, slow. See this question for more details.
This is caused by a few reasons. Jon Skeet explains it nicely:
Check that there's a parameterless constructor Check the accessibility
of the parameterless constructor Check that the caller has access to
use reflection at all Work out (at execution time) how much space
needs to be allocated Call into the constructor code (because it won't
know beforehand that the constructor is empty)
Basically, reflection has to perform all the above steps before invocation, whereas normal method invocation has to do much less.
The JITted code for instantiating B is incredibly lightweight.
Basically it needs to allocate enough memory (which is just
incrementing a pointer unless a GC is required) and that's about it -
there's no constructor code to call really; I don't know whether the
JIT skips it or not but either way there's not a lot to do.
With that said, there are many cases where Java is not dynamic enough to do what you want, and reflection provides a simple and clean alternative. Consider the following scenario:
You have a large number of classes which represent various items, i.e. a Car, Boat, and House.
They both extend/implement the same class: LifeItem.
Your user inputs one of 3 strings, "Car", "Boat", or "House".
Your goal is to access a method of LifeItem based on the parameter.
The first approach that comes to mind is to build an if/else structure, and construct the wanted LifeItem. However, this is not very scalable and can become very messy once you have dozens of LifeItem implementations.
Reflection can help here: it can be used to dynamically construct a LifeItem object based on name, so a "Car" input would get dispatched to a Car constructor. Suddenly, what could have been hundreds of lines of if/else code turns into a simple line of reflection. The latter scenario would not be as valid on a Java 7+ platform due to the introduction of switch statements with Strings, but even then then a switch with hundreds of cases is something I'd want to avoid. Here's what the difference between cleanliness would look like in most cases:
Without reflection:
public static void main(String[] args) {
String input = args[0];
if(input.equals("Car"))
doSomething(new Car(args[1]));
else if(input.equals("Boat"))
doSomething(new Boat(args[1]));
else if (input.equals("House"))
doSomething(new House(args[1]));
... // Possibly dozens more if/else statements
}
Whereas by utilizing reflection, it could turn into:
public static void main(String[] args) {
String input = args[0];
try {
doSomething((LifeItem)Class.forName(input).getConstructor(String.class).newInstance(args[1]));
} catch (Exception ie) {
System.err.println("Invalid input: " + input);
}
}
Personally, I'd say the latter is neater, more concise, and more maintainable than the first. In the end its a personal preference, but that's just one of the many cases where reflection is useful.
Additionally, when using reflection, you should attempt to cache as much information as possible. In other words employ simple, logical things, like not calling get(Declared)Method everywhere if you can help it: rather, store it in a variable so you don't have the overhead of refetching the reference whenever you want to use it.
So those are the two extremes of the pro's and con's of reflection. To sum it up if reflection improves your code's readability (like it would in the presented scenario), by all means go for it. And if you do, just think about reducing the number of get* reflection calls: those are the easiest to trim.
While reflection is most expensive than "traditional code", premature optimization is the root of all evil. From a decade-long empirical evidence, I assume that a method invoked via reflection will hardly affect performance unless it is invoked from a heavy loop, and even so there have been some performance enhancements on reflection:
Certain reflective operations, specifically Field, Method.invoke(),
Constructor.newInstance(), and Class.newInstance(), have been
rewritten for higher performance. Reflective invocations and
instantiations are several times faster than in previous releases
Enhancements in J2SDK 1.4 -
Note that method lookup (i.e. Class.getMethod) is not mentioned above, and choosing the right Method object usually requires additional steps such as traversing the class hierarchy while asking for the "declared method" in case that it is not public), so I tend to save the found Method in a suitable map whenever it is possible, so that the next time the cost would be only that of a Map.get() and Method.invoke(). I guess that any well-written framework can handle this correctly.
One should also consider that certain optimizations are not possible if reflection is used (such as method inlining or escape analysis. Java HotSpotâ„¢ Virtual Machine Performance Enhancements). But this doesn't mean that reflection has to be avoided at all cost.
However, I think that the decision of using reflection should be based in other criteria, such as code readability, maintainability, design practices, etc. When using reflection in your own code (as opposed to using a framework that internally uses reflection), one risk transforming compile-time errors into run-time errors, which are harder to debug. In some cases, one could replace the reflective invocation by a traditional OOP pattern such as Command or Abstract Factory.
I can give you one example (but sorry, I can't show you the test results, because it was few months ago). I wrote an XML library (custom project oriented) which replaced some old DOM parser code with classes + annotations. My code was half the size of the original. I did tests, and yes, reflection was more expensive, but not much (something like 0.3 seconds out of 14-15 seconds of executing (loss is about 2%)). In places, where code is executed infrequently, reflection can be used with a small performance loss.
Moreover, I am sure, that my code can be improved for better performance.
So, I suggest these tips:
Use reflection if you can do it in a way that is beautiful, compact & laconic;
Do not use reflection if your code will be executed many-many times;
Use reflection, if you need to project a huge amount of information from another source (XML-files, for example) to Java application;
The best usage for reflections and annotations is where code is executed only once (pre-loaders).
I have code that all over the place(probably 20-30 instances) does this:
<widget>.setVisible((condition == VIEW) || (condition == EDIT));
Logically I do understand that the Java compiler should and probably will optimize this to calculate it up front and simply use the calculated boolean.
My question is is there any way to actually verify that this is the case?
CLARIFICATION
condition is a private class member with no way to modify it past construction.
Disassemble the class file with javap, e.g.
javap -c com.example.ClassName
to see the bytecode source. But why not just guarantee the optimization by extracting into a temp boolean variable?
is there any way to actually verify that this is the case?
You could try to verify this by looking at the bytecode disassembly, then at the machine code produced by HotSpot, etc.
However, I think this strategy is fraught with difficultly. It is also fragile, since the result depends on the compiler/JVM and on the exact nature of condition (is it local? a class member? final? volatile?)
If you care about the optimization for performance reasons [1], my advice would be to perform it manually, by factoring out the common expression.
[1] I assume that you've profiled the code, and know for a fact that this is a bottleneck.
Disassemble the byte code.
That said, these kinds of optimizations may be done at run time, may depend on the declaration of condition, depend on where the conditions are located, and so on. Tracking down optimizations such as this is non-trivial in all but the simplest use cases.
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.