Showing posts with label performance. Show all posts
Showing posts with label performance. Show all posts

Friday, July 30, 2010

Better way of using Lists in loops


Target audience: Beginners

As I always believe, we can think of in anyways to improve the performance of our application. In this post, I explain how we can use loops effectively for list iteration. In most of my projects, I have seen developers code list iteration as follows

for (int j = 0; j < aList.size(); j++) {
....
}

There is nothing wrong in this code can change this piece of code to perform well. If you see carefully, the aList.size() will be invoked every time before the next iteration of loop starts. So, what we can do is, we can assign the size of the list to a variable and use that variable inside the loop. Check the code bellow

int size = aList.size();
for (int j = 0; j < size; j++) {
....
}

This will improve the performance a bit. I can prove this by running the following benchmarking program.

package basics;

import java.util.ArrayList;
import java.util.List;

public class ListSizeExample {
public static void main(String[] args) {

long start = 0;
long end = 0;
List aList = new ArrayList();
for (int i = 0; i < 50; i++) {
aList.add(i);
}

// Using list.size() in the loop
start = System.nanoTime();
for (int i = 0; i < 100; i++) {
for (int j = 0; j < aList.size(); j++) {

}
}
end = System.nanoTime();
System.out.println("Using aList.size(): " + (end - start) / 100);

// Using size, size is assigned with value of list.size()
start = System.nanoTime();
for (int i = 0; i < 100; i++) {
int size = aList.size();
for (int j = 0; j < size; j++) {
}
}
end = System.nanoTime();
System.out.println("Using size: " + (end - start) / 100);
}
}

I have an outer loop for each benchmark code block which runs 100 times and this is just to get the average time taken for the actual loop. If you run the code, you will get an output similar to the following one

Using aList.size(): 3765
Using size: 1256

This proves that the code perform better with a assigned value of length then directly using the list.size() inside the loop

Wednesday, July 28, 2010

Improve the Application’s performance by using primitive constants


Target audience: Beginners

We use hundreds of constants in our application. It’ll be even thousands in a large scale projects. These constants are used again and again at runtime. Improving the performance of an application in any ways is advisable.So, it will be great if we can think about improving the performance while using constants.
I would suggest using primitive constants where ever it is possible than using String constants. It is advisable not only for better memory usage but also for better performance. The following benchmark program shows the difference. The most possible usage of constants is comparison. So i use comparison for benchmarking.

package basics;

public class ConstantsExample {

public static final int RED = 1;
public static final int GREEN = 2;

public static final String SRED = "RED";
public static final String SGREEN = "GREEN";

// Main methods
public static void main(String[] args) {
long start = 0;
long end = 0;
int red = 1;
String sred = "RED";

// Benchmark primitive constants
start = System.nanoTime();
for (int i = 0; i < 100; i++) {
if (RED == red) {
}
}
end = System.nanoTime();
System.out.println("Primitive comparision: "+ (end - start));

// Benchmark String constants
start = System.nanoTime();
for (int i = 0; i < 100; i++) {
if (SRED.equals(sred)) {
}
}
end = System.nanoTime();
System.out.println("String comparision: "+(end - start));
}
}

If you run this program then you will get the results similar to bellow one

Primitive comparision: 4610
String comparision: 21721

Looks good ha!

Tuesday, June 29, 2010

How to use isDebugEnabled() efficiently


Target audience: Beginners
We all use loggers for debugging the application in-case if there were any issues. We all write debug statements in our code.I would like to share my experience of how effectively we can use
debug statements. We should write the debug statements which do not impact on our application performance. Lets see how we can do it. I use log4j for logging.

this is how we write debug code

log.debug(" some informantion");
...
log.debug("some informantion : " + variale);

We can see, there are some string concatenations happening here. We all know that string concatenation is very expensive means that it badly affect the application performance.if you see the above code, it will be executed even if the log level is set to INFO,WARN or ERROR. if we restrict these code to be executed only if DEBUG level is enabled, then we can improve the performance of the application. How we can do it? See bellow

if(logger.isDebugEnabled()){
log.debug(" some informantion");
}
.....
if(logger.isDebugEnabled()){
log.debug("some informantion : " + variale);
}

These conditions we added will check whether the log level is set to DEBUG. The log statements will be executed only if the log level is set to DEBUG. This will help to improve the performance.
But the normal practice is the developers do not check for Debug level when there is no string catenation as they think that it does not impact on performance. But it slightly impacts.

Let me explain with sample code

package test;

import org.apache.log4j.Logger;

public class MyLogger {
private Logger logger = Logger.getLogger(this.getClass().getName());

public void check() {

long withCOunt = 0;
long withOutCount = 0;

for (int i = 0; i < 1000; i++) {

// with debug
long start = System.currentTimeMillis();
for (int n = 0; n < 1000; n++) {
if (logger.isDebugEnabled())
logger.debug(n);
}
long end = System.currentTimeMillis();
withCOunt = withCOunt + (end - start);

// with out debug
long start2 = System.currentTimeMillis();
for (int j = 0; j < 1000; j++) {
logger.debug(j);
}
long end2 = System.currentTimeMillis();
withOutCount = withOutCount + (end2 - start2);
}

System.out.println("Total Time Elapsed(With isDebugEnabled) : " + withCOunt);
System.out.println("Total Time Elapsed(Without isDebugEnabled) : " + withOutCount);
}

public static void main(String[] args) {
MyLogger myLogger = new MyLogger();
myLogger.check();
}
}

You should configure log4j or any other loggers. I do not cover configuration here. I use log4j here.
I have one method which has two loops and both of them do the same work but only the difference is one loop has isDebugEnabled() checking. I try to get the accumulated time by running 1000 times to get fairly good results.

// with out debug
....
logger.debug(j);

// with debug
....if (logger.isDebugEnabled())
logger.debug(n);


If you run the application with log level WARN.
The out put will be similar to the following:
Total Time Elapsed(With isDebugEnabled) : 15
Total Time Elapsed(Without isDebugEnabled) : 47

And you run the application with log level DEBUG.
Total Time Elapsed(With isDebugEnabled) : 119704
Total Time Elapsed(Without isDebugEnabled) : 118393

The results will vary based on the machine memory configurations. But if you see, the performance is much better when we use isDebugEnabled() check with log level greater than DEBUG and the performance is fairly equal with loge level DEBUG .