Will one-time usages of local variables be optimized at compile time? - java

double calcTaxAmount() {
double price = getA() * getB() + getC();
double taxRate = getD() + getE();
return price * taxRate;
}
The function above calculates the amount of tax payment.
The price and the rate are calculated by calling some other functions.
I introduced two local variables price and taxRate to just improve code readability, so both will be used only once.
Will those kinds of "one-time" local variables be substituted and inlined at compile time with most modern compilers?

Obviously, it depends on the compiler. Quite a few compilers are actually brain-dead when it comes to optimization, because they are dealing with dynamic languages which are complex enough that most optimizations are invalid and many others are only safe if very restrictive conditions are met (for instance, any function call could have nearly any effect). For instance, all Python implementations feature a compiler, but most of them only do very few peephole optimizations, which may not be sufficient to eliminate all overhead.
That said, if you're talking about statically typed languages (which your example hints at), then usually yes. Liveness analysis can detect the equivalence (you still need a storage location for, but the lifetime is the same), and any reasonably register allocator can avoid spilling the values needlessly.
That said, this is a really bad focus for optimization. If you actually want to make stuff faster, look at the final code and profile with realistic scenarios. And if you're going to micro-optimize, apply some common sense. Even assuming this function is a hotspot, the actual computation and getting the values may easily take 100x more time. A non-inlined function call takes pretty long compared to a stack store, and a cache miss is also pretty cost at this level.

Generally yes.
Java only optimises code to native code after it has been called many time (10,000 time by default) If the method is not calls very much it won't make much difference in any case.
Even if it makes a difference of say 1 ns each, you would need to call this method 1 billion times to add a delay of 2 seconds. If its only 10 million times you are unlikely to notice the difference.

As long as the compiler can prove that they aren't aliased and modified externally, the compiler should be able to optimize them away (and I suspect that it can determine that here).
If you make them const I can't think of a compiler that couldn't optimize that.
All that said, this sounds like premature optimization and I wouldn't change the code even if it's fractionally slower because it adds to clarity.

Depends entirely on the compiler for C. Presumably yes for current compilers with proper optimization options turned on.
For Java it will not be optimized by the compiler (javac), but it may get optimized by the JIT when the code actually executes.
That beeing said, those local variables add very little overhead anyway. If the compiler decides to optimize the expressions to the equivalent of:
return (getA() * getB() + getC()) * (getD() + getE());
It will still require some form of temporary storage (stack or register) to store the intermediate results of the subexpressions. So it shouldn't make much of a difference anyway.
I wouldn't worry about it and go with what offers better readability.

Related

Java Multiplication Optimization

I am currently working on code that will have hundreds of thousands of iterations and want to know if modern Java compilers automatically handle intermediate values during optimization into assembly.
For instance, I have the following code in the loop (simplified):
arrayA[i] += doubleA*doubleB;
arrayB[i] += doubleA*doubleB;
Is a modern Java compiler 'intelligent' enough to store doubleA*doubleB into a multiplication register (and then proceed to read from the multiplication register for the second array, avoiding a second floating point operation)? Or, would I be better off with the following:
double product = doubleA*doubleB;
arrayA[i] += product;
arrayB[i] += product;
For the second option, I would primarily be concerned about the overhead of Java's garbage collector dealing with the product variable every single time it goes out of scope.
If you are running the code millions of times it is highly probable that the code will be JIT compiled. If you want to see the JIT output, and verify that it is being natively compiled you can enable that with a JVM flag (you will also have to compile a library beforehand (the library doesn't come pre-packaged due to licensing issues)).
When the JIT compiles code into native machine code it will usually perform optimizations on the code. There is also a flag which optimizes it more and more over time as the usages go up. It should be noted that JIT compilation won't usually occur until the function has been executed around 10,000 times, unfortunately there is no way to force the JIT to compile code at program launch. Presumably the JIT shouldn't have any overhead, it will probably compile the code in the background on another thread, and then inject the native code when it is finished (JIT compilation should still only take less than half a second).
As for the storing the result into a double, that won't have any negative performance impact. Also you don't need to worry about the GC for that, since it is a primitive type it is declared on the stack and popped off after the scope exits (the variable will be re-declared in the next loop iteration).
You'll practically never know what a jit does, but you can easily look at the bytecode with javap. If the javac/ide didn't optimize it, I won't presume the jit will. Just write good code, it easier on the eyes anyway.

Are variable definitions that are used once optimized?

Consider the following method:
private static long maskAndNegate(long l) {
int numberOfLeadingZeros = Long.numberOfLeadingZeros(l)
long mask = CustomBitSet.masks[numberOfLeadingZeros];
long result = (~l) & mask;
return result;
}
The method can be abbreviated to:
private static long maskAndNegate(long l) {
return (~l) & CustomBitSet.masks[Long.numberOfLeadingZeros(l)];
}
Are these two representations equal in actual run time? In other words, does the Java compiler optimize away the unnecessary definition of extra variables, that I've placed for readability and debugging?
The Java compiler itself hardly does any optimization. It's the JIT that does almost everything.
Local variables themselves are somewhat irrelevant to optimization though - a multi-operator expression still needs the various operands logically to go on the stack, just in unnamed "slots". You may well find that the generated bytecode for your two implementations if very similar, just without the names in the second case.
More importantly, any performance benefit that might occur very occasionally from reducing the number of local variables you use is almost certainly going to be insignificant. The readability benefit of the first method is much more likely to be significant. As always, avoid micro-optimizing without first having evidence that the place you're trying to optimize is a bottleneck, and then only allow optimizations which have proved their worth.
(By the time you've proved you need to optimize a particular method, you'll already have the tools to test any potential optimization, so you won't need to guess.)
The code is not significantly large enough to be optimized for starters. And in the second way you are just saving the memory used for storing references to numberOfLeadingZeros and all.
But when you will use this code significantly enough on runtime such as 10000 times at least, then JIT will identify it as HOT code and then optimize it with neat tricks such as Method Inlining and similar sorts.
But in your case preferable option is first one as it is more readable.
You should not compromise Readability for small optimizations.

Is there any difference between these statements?

Is there any difference between:
String x = getString();
doSomething(x);
vs.
doSomething(getString());
Resources and performance wise, Especially is it's done within a loop for tens, hundreds or thousands of times?
It has the same overhead. Local variables are just there to make your life easier. At the VM level they don't necessarily exist and certainly not anymore when machine code is run.
So what you need to worry about here is getString(), whether it is potentially expensive. x has very likely no effect at all.
Let me first begin by saying that your overriding goal should almost always be to maintain code readability. Your compiler is almost always better at trivial optimizations than you are. Trust it!
In response to your specific example: the bytecode generated for each example IS different. It didn't appear to make much difference though, because there wasn't a statistically significant or even consistent difference between the two approaches in a loop over Integer.MAX_VALUE iterations.
I believe both would be the same at compile time, the first may become more code readable in some cases though.
Both the statements are same. only difference is that in first approach you have used a local variable X which can be avoided using second syntax.
That largely depends on the use-case. Are you going to make repeated calls to doSomething using that exact String? Then using the local variable is a bit more efficient. However, if it's a single call or multiple calls with different Strings, it makes no difference.

Does adding local variables to methods make them slower?

This question has received a total of several paragraphs of answer. Here is the only sentence that actually tells me what I was looking for:
Your examples would make little difference since intermediate computations need to be stored temporarily on the stack so they can be used later on.
In fact, it answers my question perfectly and completely =)
Unlike all the cruft telling me "nooo don't ask that question". >_<
Like if you have a method, and you change it by increasing the number of local variables but make no other changes, does it make the method slower? Here's an example:
void makeWindow() {
Display
.getContext()
.windowBuilder()
.setSize(800, 600)
.setBalloonAnimal(BalloonAnimal.ELDER_GOD.withColor(PUCE))
.build();
}
or
void makeWindow() {
DisplayContext dc = Display.getContext();
WindowBuilder wb = db.windowBuilder();
BalloonAnimal god = BalloonAnimal.ELDER_GOD;
BalloonAnimal puceGod = god.withColor(PUCE);
wb.setSize(800, 600).setBalloonAnimal(puceGod).build();
}
Another example:
int beAnExample(int quiche) {
return areGlobalsEvil?
quiche * TAU/5:
highway(quiche, Globals.frenchFrenchRevolution);
}
or
int beAnExample(int quiche) {
if (areGlobalsEvil) {
int to5 = TAU/5;
int result = quiche * to5;
return result;
} else {
Game french = Globals.frenchFrenchRevolution;
int result = highway(quiche, french);
return result;
}
}
Really, what I'm asking is: Is the number of this sort of local variable even relevant by the time the method's compiled to bytecode? If so, what about once Hotspot gets to work on it?
This question is relevant to the code generator I'm working on.
The easy answer is no. Local variables consume runtime stack space. Allocating space for them only marginally increases the number of instructions. Your examples would make little difference since intermediate computations need to be stored temporarily on the stack so they can be used later on. Focus more on the readability of your programs rather than needless micro-optimizations.
If you're interested in looking at the actual bytecode of a class, investigate the javap program.
Don't worry about it. The compiler can do all sorts of crazy, make-your-head-asplode optimizations. Start with code that's correct and maintainable. Programmer time is worth far more than processor tiem.
Test it by running each method 1,000,000 times and divide the total time to calculate the cost per execution. In all likelihood, it won't be noticable.
Actually, Java compilers may even be smart enough to just compile it out.
Write your code for readability to reduce long term cost of maintenance. Then tune it in the 5% of places where you really need to.
The chances are that it will make little (if any) difference, and the "little" will be insignificant.
Focus on making your generator correct and maintainable, and let the Java compiler (particularly the JIT compiler) do the micro-optimization of the generated code.
Note that #Edawg's advice on looking at the bytecode is not necessarily helpful. The JIT compiler aggressively optimizes the native code that it generates from the bytecodes. It can be difficult to predict which of two bytecode sequences is going to be faster. Certainly, counting bytecodes, method calls and so on can be misleading.
The only way to be sure that you are generating "optimal" Java source code would be to compile it and benchmark it on your target platform. Even then, there's a good chance that your efforts at source-code level optimization will be negated ... by JIT compiler changes.
This is not a hotspot issue. There may need to be additional byte codes to load and store the local variables, but let the compiler worry about optimizing that.
You should concentrate on issues like null pointer checking in your generated code and how to report errors in a meaningful way that is tied to the source input that you are code generating from.

does a Java getter incur a performance penalty

if i have the code
int getA(){
return a;
}
and then do something like
int b = obj.getA();
instead of
int b = obj.a;
will that mean that the stack will have to be pushed and popped ultimately slowing down my code?
The JIT compiler will inline the method.
The code should look like
int b = obj.GetA();
I have two answers for you:
I don't think that there is a significant performance penalty for using the getter vs accessing the variable directly. I would worry more about how understandable and readable the code is than performance for this sort of decision.
According to OO design principles, which may or may not be important to you, you would normally hide the data and provide the getter method to access it—there is a detailed discussion on the merits of this approach here.
Theoretically there is some runtime penalty, due to a method call being made. In reality, this has very little effect on the overall performance due to two reasons:
Unless the obj.getA() is taking place inside the inner-most loop of your program, then its effect on the overall performance of your code will be negligible. When performance is an issue you should consider the bottleneck of your code. There's no point in optimizing code that is out not at these hot spots. In order to identify these spots you need to analyze the execution of your code via a profiler.
As #Michael was saying the JVM uses a "Just In Time" compiler/optimizer that inlines code based on actual execution. It performs just this kind of optimizations (see this talk)

Categories