Monday, August 2, 2010

Java Performance Tuning Tips

  1. Counting down (i.e. for (int i=n; i>0; i--)) is twice as fast as counting up: my machine can count down to 144 million in a second, but up to only 72 million. 
  2. Calling Math.max(a,b) is 7 times slower than (a > b) ? a : b. This is the cost of a method call. 
  3. Arrays are 15 to 30 times faster than Vectors. Hashtables are 2/3 as fast as Vectors.
  4. Use System.arraycopy(firstArray, 0, secondArray, 0, firstArray.length) method instead of iterating the first array and copying into second array.
  5. Use compound assignment operators (+=, -=, *=, and /=) instead of using normal operators.
  6. Ex: a = a+b takes longer time to execute when compared to a += b. In fact, these cause different Java byte codes to be generated.
  7. Eliminate unnecessary code in the loops and you should avoid declaring variables unnecessarily within loops.
  8. Use int instead of other primitive types because operations performed on int primitives generally execute faster than for any other primitive type supported by Java, so you should use int values whenever possible; char and short values are promoted to int automatically before arithmetic operations.
  9. Use notify() instead of notifyAll(), notify will execute faster than notifyAll().
  10. When joining couple of Stings use StringBuffer instead of String.
  11. Don't try to convert Strings to upper or lower case for String comparison.
  12. In the String Class prefer charAt() method instead of startsWith() method. From performance perspective, startWith() makes quite a few comparisons preparing itself to compare it's prefix with another string. 
  13. Don' t initialize the public instance variable in constructor if they already initialized outside the constructor. Because all public initialized instance variables are again initialized in constructor by default.
  14. Vector provides the following methods to insert elements.                                                                       addElementAt( e, index)
             addElement (e)
             add(index, e)
  15. Out of these try to avoid using methods, addElementAt( e, index) and add(index, e). The way these methods work is , all the elements are moved down between the insertion point and the end of the vector, making space for the new Element. The same works for deleting element at a Particular index. If possible, if these features are required, then try to use a different Data Structure if possible.
  16. If the approximate size of the Vector is know initially then use it. Instead of declaring Vector as,
            Vector v = newVector();
          declare it as,

            Vector v = new Vector(40);
         or  Vector v = new Vector(40,25) ; 
  17. This method indicates initial capacity of Vector is 40 and increment by 25 elements per expansion.The way the Vector is expanded is, a new Vector of double the size of currentVector is created, all the Elements in the old Vector is copied to the new Vector and then the old Vector is discarded. (During GC). This has major effect on performance.


MohanKumar said...

# When joining couple of Stings use StringBuffer instead of String

More on tip 10 - String performance :

String is immutable whereas StringBuffer and StringBuilder can change their values.

StringBuilder is more efficient than StringBuffer. The only difference between StringBuffer and StringBuilder is that StringBuilder is unsynchronized whereas StringBuffer is synchronized. So when the application needs to be run only in a single thread then it is better to use StringBuilder.

Criteria to choose among String, StringBuffer and StringBuilder

1. If your text is not going to change use a string Class because a String object is immutable.
2. If your text can change and will only be accessed from a single thread, use a StringBuilder because StringBuilder is unsynchronized.
3. If your text can changes, and will be accessed from multiple threads, use a StringBuffer because StringBuffer is synchronous.

Laurent Pireyn said...

I read your post with interest but thought I might add my two cents.

1. This is due to the instructions available on most CPUs. A loop counting up implies comparing (i.e. subtracting) the index value to the threshold value and jumping if the result is zero. A loop counting down to zero - and only to zero - can skip the comparison (subtraction) and immediately compare the index value with zero. However, since an empty loop has no point whatsoever, this is barely an optimization.

2. The body of the max method is so small that adding the cost of the method call may well multiply the whole thing by 7. However, most JVMs will probably dynamically inline such methods, especially if they're called repeatedly. The cost of a method call should almost never be an issue in Java.

6. This is once again due to the dedicated instructions that exist on most CPUs. And once again, most JVMs (or even the compilers) will choose the faster form when it becomes an issue.

7. This statement is true even outside any loop.

9. This is obviously due to the important difference between the two methods: notify wakes a waiting thread chosen at the JVM's discretion while notifyAll wakes all waiting threads. In both cases, the awakened threads will compete for the monitor as only one will be able to acquire it.

10. Even better: if you can afford Java 1.5 and your buffer is not accessed by multiple threads (i.e. is a local variable), use StringBuilder.

11. Can you elaborate on this one?

12. charAt is quite obviously faster than startsWith (you might want to fix the typo by the way), but those two methods do different things and should not be compared.

15. Linked lists should be used when doing several insertions/deletions.