Search This Blog

Showing posts with label Performance. Show all posts
Showing posts with label Performance. Show all posts

Sunday, May 13, 2012

Java Performance Tips 2


Introduction
We talked about Strings operations in the last article, now we will talk about more tips on performance tips, we will talk about the importance of creating stateless methods and class if your logic doesn't depend on the state of the object, also we will talk about object reusing and how will affect the performance by reducing the headache of garbage collection.

Take 'State or Stateless' Decision
Creating and destroying objects issue in java can cause performance issues, for example creating State classes for stateless data; a stateless class means that the data of the created object doesn't depend on the state where there is no fields or attributes that makes an object differs from other.
We can imagine that the Stateless class can say 'Use me only if your code doesn't depend on your object state, All the objects are functionally equivalent to me, you will gain besides that no creation of objects, the CPU will be happy of doing that J'



Code Example

The following StatelessClassWithoutStaticMethods class has a method called execute, where the logic of this method doesn't depend on the state of the object, while it is not static method.

package performancetest.episode2;

public class StatelessClassWithoutStaticMethods {
      public void execute()
      {
            // the logic here doesn't depend on the object state
            for (int i = 0; i < 10000; i++) {
                  System.out.println(i);
            }
      }
}

While the right version as the following:

package performancetest.episode2;

public class StatelessClassWithStaticMethods {
      public static void execute()
      {
            // the logic here doesn't depend on the object state
            for (int i = 0; i < 10000; i++) {
                  System.out.println(i);
            }
      }

}


Performance Analysis
Using TBTB (Eclipse Test & Performance Tools Platform Project), the following results are shown as follows

Java Performance Analysis
Performance Analysis










Based on this figure, the static execute method has loss approximately 18% of time from the non-static one.
That doesn't mean that you have to make all the class a static (i.e. a class has static methods only), but if you have a state method in this class depends on the object state, make this method only non-static.



Don't Create A New One If You Can What You Have
'You can use me before I go to the garbage collection, clear my data and reuse me again; we want to lessen the work on our friend garbage collection' Any object says this quote J, Creating new objects is expensive as we know as more objects we create, the garbage collection job will be more time consuming.
So if you have a chance to reuse the object again without creating a new one of the same type, do it immediately, it will improve the performance and will make the garbage collection job be easier.
Code Example
public static void fillVectorDataWithoutRecycling()
      {
            for (int i = 0 ; i < 1000 ; i ++)
            {
                  Vector v = new Vector();
                  v.add("item1");
                  v.add("item2");
                  v.add("item3");
                  System.out.println(v.get(0));
            }
      }
     

      public static void fillVectorDataWithRecycling()
      {
            Vector v = new Vector();
            for (int i = 0 ; i < 1000 ; i ++)
            {
                  v.clear();
                  v.add("item1");
                  v.add("item2");
                  v.add("item3");
                  System.out.println(v.get(0));
            }
      }


We have two methods, fillVectorDataWithoutRecycling method creates a new vector object in the loop, while fillVectorDataWithRecycling method uses one vector object and clears the vector object and reuse it.

Performance Analysis
Java Performance Analysis With/Without Vector Recycling
Performance Analysis With/Without Vector Recycling







From this figure we found that reusing the current object will cause loss approximately 50% of time (of course without taking in the consideration the hardware architecture like CPU, cache and memory).

Java Performance Tips 1 - String Operations


String Operations
There are some performance tips for String manipulation in java, one of them is the concatenation operation.
Concatenation operation can be done by appending the values on the same String object for example:
String str = new String ();
String s = "test";
str+=s;
str+="testString";
The compiler translated this simple line to the following J
str = (new StringBuffer()).append(s).append("testString").toString();
But this method is not preferable (as we will know later), one other method is using StringBuffer .


Using StringBuffer Method
StringBuffer is used to store character strings that will be changed as we know that String class is immutable, so we can concatenate the strings as follows:
StringBuffer sbuffer = new StringBuffer();
sbuffer.append("testString");

StringBuffer vs StringBuilder
Also there is another method to concatenate the String using StringBuilder which is introduced in Java 5, StringBuilder is like the StringBuffer except it is not synchronized, which means that if there are many threads, they can change it in the same time (StringBuilder is not suitable in the multithreading applications).
'Ok, why this stuff for, just for concatenate some strings!' you may ask this question, after running a sample of each and profiling the performance.

Code Example

public class StringOperations {
    public void concatenateUsingString() {
        String str = new String();
        for (int i = 0; i < 10000; i++) {
            str += "testString";
        }
    }
    public void concatenateUsingStringBuffer() {
        StringBuffer sbuffer = new StringBuffer();
        for (int i = 0; i < 10000; i++) {
            sbuffer.append("testString");
        }
    }
    public void concatenateUsingStringBuilder() {
        StringBuilder sbuilder = new StringBuilder();
        for (int i = 0; i < 10000; i++) {
            sbuilder.append("testString");
        }
    }
}

And in the main method, a simple calling to the three methods

public static void main(String[] args) {
        StringOperations soperations = new StringOperations();        
        soperations.concatenateUsingString();
        soperations.concatenateUsingStringBuffer();
        soperations.concatenateUsingStringBuilder();
    }


The result is like the following:
The Results by seconds







The Results by percentage









I have used the Eclipse Test & Performance Tools Platform Project (TPTP) to validate the results, just right click on the project and choose 'Profile As'.

Profile As













Then choose 'ProfileàProfile Configuration '


Profile Configuration


















This result shows the big performance issue of using the String concatenation (Plus operation),
the profiler tells us that the calling of concatenateUsingStringBuffer and concatenateUsingStringBuilder (approximately 0.08%) of time are nothing with respect to concatenateUsingString (99.85% of time).
    http://www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html
    http://leepoint.net/notes-java/data/strings/23stringbufferetc.html