Tuesday, July 17, 2007

Default Optimization by Javac engine

Sometimes you would have wondered why code is not working!!!

You just made some changes in classes (some static and final values) but still have no use, it won’t reflect at all in the main application.

Well its not always that you did something wrong, it may be effect of default optimization done by “javac”, which you may not be aware of.

For Example:
Say you have a constants class, let one of the constants be DefaultArraySize as below

package mypack;
public class MyConstants{
/* some code here */
public static final int DefaultArraySize=10;
/* some code here */
}

And you are using it in some class say MyApp as following

import mypack.MyConstants;
public class MyApp{
public static void main (String [] args){
/* some code here */
String array[]=new String[MyConstants.DefaultArraySize];
System.out.println(“Array Size: ”+array.length());
}
}

Now compile and run both classes the output will be 10, here the problem starts try to change value of DefaultArraySize to something else say 20, compile MyConstants class again, now try to run MyApp class, so what’s the result 20 – well no its 10 again!!!

Project Manager: So what went wrong?
Intelligent Developer: Don’t know why, JVM is behaves strange sometimes. S sometimes just rebuilding whole application works.

Clearly our too intelligent code guru doesn’t know the exact problem, but anyways this will not stop him as just rebuilding of app will do the trick, but this is just a small problem think how many things can be there, which can go just unnoticed!!!

Frustrated Developer: Why the hell they wrote a Java compiler is such a way? Do they have personal problem with me?
Answer: Well Sun didn’t wrote Javac in such way to trouble our code guru, it’s something they optimized to give you better performance, its not at the cost of developing, its just because our developer is not coding in smart way.

So now we are at a stage to discuss optimizations done by Javac (we will discuss about most common optimizations done by Javac), which can be worthwhile to keep in mind while coding.

But before we go on to talk about optimizations done by Javac, we should keep it in mind that Javac is not an full power optimization engine, it provide some common optimizations only, so we can’t fully depend on Javac alone if at all we plan to optimize our code automatically later. (See my blog for Java Performance Tuning to get more information about why optimization required, how to optimizing your code, and some off the shelf Java optimizing compilers)

Optimizations done by Javac

  1. Constant Removal
  2. Inlineing function calls
  3. Changing/Removing code

Constant Removal: Javac removes a constant if it is involved in some calculation with other constant and returns a single value. For Example-

Original Code: int intVar=10*9;
Optimized by compiler: int intVar=90;

Original Code: String str=”Some Text: “+ (9*10);
Optimized by compiler: String str=”Some Text: 90”;

Original Code: String str=”Some Text: “+ Constnats.someConst; //say its value is 140
Optimized by compiler: String str=”Some Text: 140”;

Inlining function calls: Function calls to private members of the same class are inlined also calls to static members of other classes are inlined.

Changing/Removing code: Javac sometimes alters the code flow to optimize the performance. For Example -

Suppose you built a customized logger, to log all the messages, and say you are having a static variable as
public static final boolean Debug=true;

And you are using it as

If (MyConstants.Debug){
System.out.println(“some debug data”);
}

You compiled this code, and now you changed the value of Debug to false what will happen, now as you are smart enough the constant removal (see 1) will change the code to if condition with true value and the changes will not be affected, yes you are correct. But Javac goes to one more step and removes the whole condition from there, thus the compiled byte code will have code simmilar to what will be produced if below code is compiled

System.out.println(“some debug data”);

That is “if (true)” is removed so that JVM needs to run one less code of line and thus enhancing the performance a bit more.

With this I would like to close this Blog with hope it helped you all.

There are also many other optimizations that are used by commercial Optimizing compilers; you can refer to my Java Performance Tuning Blog for more details.

No comments: