Java Performance Tuning

Java(TM) - see bottom of page

|home |services |training |newsletter |tuning tips |tool reports |articles |resources |about us |site map |contact us |
Tools: | GC log analysers| Multi-tenancy tools| Books| SizeOf| Thread analysers| Heap dump analysers|

Our valued sponsors who help make this site possible
JProfiler: Get rid of your performance problems and memory leaks! 

Training online: Concurrency, Threading, GC, Advanced Java and more ... 

Newsletter no. 13, December 26th, 2001

JProfiler
Get rid of your performance problems and memory leaks!

Modern Garbage Collection Tuning
Shows tuning flow chart for GC tuning


Java Performance Training Courses
COURSES AVAILABLE NOW. We can provide training courses to handle all your Java performance needs

Java Performance Tuning, 2nd ed
The classic and most comprehensive book on tuning Java

Java Performance Tuning Newsletter
Your source of Java performance news. Subscribe now!
Enter email:


Training online
Threading Essentials course


JProfiler
Get rid of your performance problems and memory leaks!


As promised, I've started categorizing the tips at the website. If you go over to the tips page, you'll see that there is a new format. The old tips page is still accessible (as rawtips), but I'm categorizing every tip and each category will result in a page containing only the tips for that category. I'll add a new category about twice a month. The initial two categories are JDBC and synchronization.

Now on with the news. This month we have a bumper crop of URLs. I guess everyone is trying to get out their articles before the holiday season. JDBC certainly seems to have come of age. The experienced tips being written are one indication of that, but the clincher is a new book called "Oracle JDBC" - specialization within specialization.

Other than that, we have J2EE articles (mainly EJB but other aspects too, not forgetting that JDBC is also a component of J2EE); a variety of other articles, some more chapters from "Java Platform Performance" and pages from another recently built Java performance focused website, precisejava.com. That's Ravi Kalidindi trying to steal my thunder: competition for me, more information for you. Fortunately, I learned a long time ago that if you don't have any competition, the field can't be worth much, so I'm actually delighted to see another website dedicated to Java performance.

As usual Kirk follows the discussion groups, with one discussion in particular, on microbenchmarks, generating significant coverage. Note that I've added an index into Kirk's roundup from the main newsletter page so that you can reach it directly if that's where you like to start.

And here's my usual reminder to our Japanese readers that Yukio Andoh's translation should be available at http://www.hatena.org/JavaPerformanceTuning/ in a while.

News

Java performance tuning related news.

Upcoming

Links

Tools

Recent Articles

All the following page references have their tips extracted below.

Older Pages

All the following page references have their tips extracted below.

Jack Shirazi


Kirk's roundup

The question of micro benchmarks and micro performance tuning continues to be a very common topic of discussion in many different forums. Most recently, there was a posting to one of the lists concerning the cost of of casts. The poster described how he had always used the toString() method when retrieving String objects from a HashMap instead of casting. One day he got curious and wrote a micro benchmark to empirically compare the two techniques. In his post, he supplied both source and some results. Everyone who responded to his posting suggested that one should never run a micro benchmark.

(The String.toString() method, shown here, is pretty simple. It causes an Object to narrow to a String without explicity needing a cast.)

/**
* This object (which is already a string!) is itself returned. 
*
* @return  the string itself.
*/
public String toString() {
    return this;
}

Some responders quite correctly pointed out that tuning efforts should be saved for application bottlenecks. But, this point only shows that there is some confusion concerning the difference between macro and micro performance tuning and benchmarking. Other performance tuning experts consider that micro benchmarks produce erroneous and consequently misleading results. Many valid points against microbenchmarks were raised, including that a micro benchmark can totally mislead the compiler, HotSpot and JITs. These tools may make decisions that differ quite significantly from the decisions they would make when analyzing a real application. It can be difficult to reproduce real life while conducting a micro benchmark. Since so many people stand against the validity of micro benchmarks, does this mean that one should automatically ignore this technique? While it maybe difficult to reproduce real life in a micro benchmark, it is clearly not impossible. Given the potentially valuable information concerning the performance that a particular algorithm or coding style may produce, it is my opinion that it would be a mistake to ignore this technique.

Consider the role of a compiler. It's job is to turn your code into byte code. To carry out this translation, the compiler must understand what it is that you are trying to do. The easier it is for the compiler to understand your code, the better chance it has to produce better byte code (i.e. optimize it). Thus, your coding style can make or break a compiler's ability to produce optimal byte code. But, what constitutes a good coding style? Micro benchmarks can help answer this question.

However, one must be aware of the pitfalls. Lets use the toString() vs. String cast example to demonstrate. The following code fragment is an implementation of a micro benchmark:

long start = System.currentTimeMillis();
//
for( i=0; i < 1000000; i++) {
    String s = map.get(key).toString();
}
//
long finished = System.currentTimeMillis();
System.out.println(finished - start);
//
start = System.currentTimeMillis();
for (i=0; i < 1000000; i++) {
    String s =  (String)map.get(key);
}
finished = System.currentTimeMillis();
System.out.println(finished - start);

On the surface, it would appear that this code fragment will answer the question of which technique is faster. But, on closer inspection, some doubts should begin to appear. For starters, the code is much more compact than it would be in a real application. Does this allow the compiler to make some optimizations that would not exist in a real application? What about the String declaration inside the first loop. Will that result in a timing difference? Most sensible compilers will move the declaration out of the loop, does yours? Some compilers may recognize that the body of the loops only need to be executed once and may optimize away the loop.

We also have to consider that with Java, the story doesn't end with the compiler. One must consider the effects of HotSpot and JITs. Again, will the code in the micro benchmark be optmized differently than that found in an application? If the code is optimized differently, does it matter?

Lets again turn to our original question and see if a micro benchmark can provide the answer. I wrote 3 different versions of the original micro benchmark: the code is listed at the end of the roundup.

In the end, I could find no real difference between the code that performed an explicit cast and the code that called the toString() method. I used the JDK version 1.3.0-C. The posted results for the JDK 1.3.1 were 270ms for the toString() and 251ms for the cast. The results for the JDK 1.2.2, were 1512ms for the toString() and 1552ms for the cast. Since I find code that contains explicit casts easier to read, I'd opt for that coding style rather than make the method call.

While it is true that micro benchmarks are fraught with difficulties, done carefully, they still can provide useful information that can have an effect on your coding style. As I was once told by one of the best performance tuning guru's that I know, "you can fill a water tower with a tea spoon".

The JavaRanch

Now onto the discussion groups. This month, we will start with the Java Ranch.

Readability is amongst the primary motivations for using constants. So, is there a performance impact from using constants (those fields declared static final)? Since the compiler will inline anything that it can resolve at compile time, the answer is there is not.

Last month, I wrote about the discussion regarding initializating fields to null. Well, the discussion continued and evolved into an even more interesting discussion focusing on objects, object references, where they live and when and what effect this has on garbage collection. The term "object" is overloaded so much that it is easy to confuse even experts. Thus we need to be mindfull that when one talks about an object, they may actually be referring to a reference to that object. All non-primitive variable declarations, be they field, static, local, or method parameters are object references. Objects exist only in heap space. Fields will be stored in heap space as an object reference. Local variables, method parameters and return values are object references that are stored on the stack. How does this effect GC? The rule is, an object is eligible for GC when it is no longer referenced. Consequently, we can determine when an object will be eligible for GC. But, how the execution stack is implemented in the VM is up to the JVM developers. Although we may reason than local variables and method parameters become eligible for GC as soon as a method returns, in reality, this is an implementation detail for the JVM implementors and is beyond our control. If a local variable is large enough, it maybe wise to set it's object reference to null before the method return.

Just before press, another interesting garbage collection discussion appeared. The poster has an application that consumes many URLConnection and BufferedReader objects. For some reason, the application is throwing an OutOfMemoryException which of course halts the JVM. The local sheriff offered some great advice on how to track GC related memory problems.

JavaGaming.org

Next we move to the discussion group found at Java Gaming.

Here's an interesting result. A question was raised as to the differences in performance between C++ and Java when calcuating Fast Fourier Transforms (FFT). It was noted that for smallish vectors (4^6), Java is half as fast as C++. Between the sizes of 4^6 4^7, Java catches and and is sometimes faster than C++. Note, one should be wary of the effects of the HotSpot compiler kicking in when performing these types of tests.

There was yet another issue with GC. A poster was commenting that GC was causing his display to jitter. The problem was further isolated to the Graphic.drawImage() method call. After some investigation, it was discovered that when you call drawImage with a transform, it creates a temporary image object. Removing the transform avoided the creation of the temporary image and smoothed out the video.

The Server Side

And finally, from the Middleware company we have a couple of intesting posts. The first one has to do with performing a JDBC call while inside a constructor. All of the responses suggested that the JDBC code should be removed from the constructor. One respondant suggested that the JDBC call be contained in a factory object (Factory Pattern). As much as I feel that factory objects are over used, this seems like a practical solution to this problem.

There was yet another call for profiling tools. In addition to the usual suspects, jProbe and OptimizeIt, VTune from Intel was offered as a possibility. You can find it at www.intel.com/software/products/vtune.

In another thread one poster tested local interfaces for EJB and found no improvement. The responders pointed out the the app server (Weblogic) automatically uses local calls for locally reachable EJBs, even when the EJBs are built using remote interfaces. This improves performance, and explains the lack of improvement.

CastTest.java

/*
 * @author Kirk Pepperdine
 * @since Dec 5, 2001
 */
import java.util.HashMap;
//
public class CastTest {
//
    /**
     * Calcuate the overhead of performing a lookup and assignment.
     * This method performs every step execpt storing the objects
     * as a String.
     */
    public static long overhead(int iterations, HashMap map, String key) {

Object[] object = new Object[iterations]; Object[] object2 = new Object[iterations]; long startTime = System.currentTimeMillis();

for (int i = 0; i < iterations; i++) { object[i] = map.get(key); object2[i] = object[i]; }

return System.currentTimeMillis() - startTime; } // /** * Calculate the cost of performing a cast. */ public static long castTime(int iterations, HashMap map, String key) { // Object[] object = new Object[iterations]; String[] string = new String[iterations]; long startTime = System.currentTimeMillis(); // for (int i = 0; i < iterations; i++) { object[i] = map.get(key); string[i] = (String)object[i]; } // return System.currentTimeMillis() - startTime; } // /** * Calculate the cost of performing a toString() method call */ public static long toStringTime(int iterations, HashMap map, String key) {

Object[] object = new Object[iterations]; String[] string = new String[iterations]; long startTime = System.currentTimeMillis(); for (int i = 0; i < iterations; i++) { object[i] = map.get(key); string[i] = object[i].toString(); } return System.currentTimeMillis() - startTime; } // public static void main(String[] args) { HashMap map = new HashMap(); String s = "xxxx"; map.put(s,s); int iterations = Integer.parseInt(args[0]); long overHead = CastTest.overhead(iterations,map,s); long cast = CastTest.castTime(iterations,map,s); long toString = CastTest.toStringTime(iterations,map,s);

System.out.println("overhead is " + overHead + "ms"); System.out.println("toString() " + (toString - overHead) + "ms"); System.out.println("cast " + (cast - overHead) + "ms"); } }

Kirk Pepperdine.


Tips

http://www.onjava.com/pub/a/onjava/2001/12/05/optimization.html
Measuring JDBC performance (Page last updated December 2001, Added 2001-12-26, Author Jack Shirazi). Tips:

http://www.onjava.com/pub/a/onjava/2001/12/19/oraclejdbc.html
Oracle JDBC tips (Page last updated December 2001, Added 2001-12-26, Author Donald Bales). Tips:

http://www.oreilly.com/catalog/jorajdbc/chapter/ch19.html
Chapter 19, "Performance" of Java Programming with Oracle JDBC (Page last updated December 2001, Added 2001-12-26, Author Donald Bales). Tips:

http://www.fawcette.com/javapro/2002_01/magazine/columns/weblication/
Database performance (Page last updated December 2001, Added 2001-12-26, Author Peter Varhol). Tips:

http://www-105.ibm.com/developerworks/education.nsf/java-onlinecourse-bytitle/56A6275393F0BE5786256AFD004DBBB4?OpenDocument
JDBC tutorial (requires free registration) (Page last updated November 2001, Added 2001-12-26, Author Robert J. Brunner). Tips:

http://www-105.ibm.com/developerworks/education.nsf/java-onlinecourse-bytitle/975BFD2C367CFFD686256B0500581B3B?OpenDocument
Advanced JDBC tutorial (requires free registration). (Page last updated November 2001, Added 2001-12-26, Author Robert J. Brunner). Tips:

http://developer.java.sun.com/developer/technicalArticles/J2EE/J2EEpatterns/
Performance optimizing design patterns for J2EE (Page last updated December 2001, Added 2001-12-26, Author Vijay Ramachandran). Tips:

http://www.onjava.com/pub/a/onjava/2001/12/19/eejbs.html
EJBs are wonderful (Page last updated December 2001, Added 2001-12-26, Author Tyler Jewell). Tips:

http://www.fawcette.com/javapro/2001_12/magazine/features/kkothapalli/
EJB performance tips (Page last updated December 2001, Added 2001-12-26, Author Krishna Kothapalli and Raghava Kothapalli). Tips:

http://www.onjava.com/pub/a/onjava/2001/12/12/jms_not.html
JMS & CORBA (Page last updated December 2001, Added 2001-12-26, Author Steve Trythall). Tips:

http://www.javaworld.com/javaworld/jw-12-2001/jw-1207-hprof.html
The hprof profiler (Page last updated December 2001, Added 2001-12-26, Author Bill Pierce). Tips:

http://www.onjava.com/pub/a/onjava/excerpt/JavaRMI_10/index.html
Chapter 10, "Serialization" from "Java RMI" (Page last updated November 2001, Added 2001-12-26, Author William Grosso). Tips:

http://developer.java.sun.com/developer/community/chat/JavaLive/2001/jl1113.html
Sun community chat on iPlanet (Page last updated November 2001, Added 2001-12-26, Author Edward Ort). Tips:

http://www.javaworld.com/javaworld/jw-12-2001/jw-1207-java101.html
Article about garbage collection and finalization. (Page last updated December 2001, Added 2001-12-26, Author Jeff Friesen). Tips:

http://www.fawcette.com/javapro/2002_01/magazine/features/rgrehan/
How to Climb a B-tree (Page last updated December 2001, Added 2001-12-26, Author Rick Grehan). Tips:

http://developer.java.sun.com/developer/technicalArticles/releases/nio/
The java.nio packages (updated) (Page last updated December 2001, Added 2001-10-22, Author John Zukowski). Tips:

http://www.javaworld.com/javaworld/jw-12-2001/jw-1214-jylog.html
JyLog logger (Page last updated December 2001, Added 2001-12-26, Author Sanjay Dahiya). Tips:

http://www.devx.com/premier/mgznarch/javapro/2001/01dec01/sl0112/sl0112-1.asp
Creating Web-based, interactive graphics. (Page last updated December 2001, Added 2001-12-26, Author Steve Lloyd). Tips:

http://www.javaworld.com/javaworld/javaqa/2001-12/01-qa-1207-ziprmi.html
Data compression (Page last updated December 2001, Added 2001-12-26, Author Tony Sintes). Tips:

http://www.precisejava.com/javaperf/j2ee/EJB.htm
EJB performance tips (Page last updated November 2001, Added 2001-12-26, Authors Ravi Kalidindi and Rohini Datla). Tips:

http://www.precisejava.com/javaperf/j2ee/JDBC.htm
JDBC performance tips (Page last updated November 2001, Added 2001-12-26, Authors Ravi Kalidindi and Rohini Datla). Tips:

http://www.precisejava.com/javaperf/j2ee/Servlets.htm
Servlet performance tips (Page last updated November 2001, Added 2001-12-26, Authors Ravi Kalidindi and Rohini Datla). Tips:

http://www.precisejava.com/javaperf/j2ee/JSP.htm
JSP performance tips (Page last updated November 2001, Added 2001-12-26, Authors Ravi Kalidindi and Rohini Datla). Tips:

http://www.precisejava.com/javaperf/j2ee/JMS.htm
JMS performance tips (Page last updated November 2001, Added 2001-12-26, Authors Ravi Kalidindi and Rohini Datla). Tips:

http://www.precisejava.com/javaperf/j2ee/Patterns.htm
Pattern performance tips (Page last updated November 2001, Added 2001-12-26, Authors Ravi Kalidindi and Rohini Datla). Tips:

http://java.sun.com/docs/books/performance/1st_edition/html/JPIOPerformance.fm.html
Chapter 4, "I/O Performance" of "Java Platform Performance: Strategies and Tactics." (Page last updated 2000, Added 2001-12-27, Author Steve Wilson and Jeff Kesselman). Tips:

http://java.sun.com/docs/books/performance/1st_edition/html/JPRAMFootprint.fm.html
Chapter 5, "RAM Footprint" of "Java Platform Performance: Strategies and Tactics." (Page last updated 2000, Added 2001-12-27, Author Steve Wilson and Jeff Kesselman). Tips:

http://java.sun.com/docs/books/performance/1st_edition/html/JPClassLoading.fm.html
Chapter 6, "Controlling Class Loading" of "Java Platform Performance: Strategies and Tactics." (Page last updated 2000, Added 2001-12-27, Author Steve Wilson and Jeff Kesselman). Tips:

Jack Shirazi


Last Updated: 2024-08-26
Copyright © 2000-2024 Fasterj.com. All Rights Reserved.
All trademarks and registered trademarks appearing on JavaPerformanceTuning.com are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries. JavaPerformanceTuning.com is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
URL: http://www.JavaPerformanceTuning.com/newsletter013.shtml
RSS Feed: http://www.JavaPerformanceTuning.com/newsletters.rss
Trouble with this page? Please contact us