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. 32, July 29th, 2003

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!


We already know the from feedback we get that our newsletters are amongst the most respected in the industry. Our influence on opinion formers keeps growing all the time. We don't keep any details about subscribers to the newsletter, apart from your email addresses. But before we throw away the details, I have a quick visual scan of subscriptions, just to get a feel of who is joining. Our subscribers include every level of the company hierarchy: Presidents, CEO's, CIO's, V.P.s, Directors, Managers, Architects, and so on right through the spectrum of I.T. positions. You're in good company if you are reading this.

A note from this newsletter's sponsor

Measure, analyze and maximize J2EE application performance
during load testing with PerformaSure. Read the Aberdeen
white paper "Honing In on J2EE Performance Assurance".

Well we didn't quite get to our intended weekly publication mode over the last month, due to being distracted with a number of other initiatives, but we did manage to publish one week, so we'll see if we can do better this month.

In this month's newsletter we list our usual raft of articles, tools, and more. I continued extracting tips from some more JavaOne presentations. I also have a new blog at java.net, and seem to have made the most noteworthy performance news contribution of the month by compiling a list of case studies of successful Java sites (see news below). Included in the list is eBay, serving 380 million pages per day last year, and expected to serve 1 billion per day by 2005. Given that eBay is highly transactional and data dependent, and many of the transactions are the kind that require audit trails, it shows what a Java enterprise site can scale to.

In addition, we have most of our usual sections. Kirk's roundup covers tokenizing, result set processing, data structures, a fascinating discussion on OutputStream.write blocking, and more. Our question of the month looks at whether making an object static to reuse it is good practice; Javva The Hutt reports his holiday surfing adventures; and, of course, we have many new performance tips extracted in concise form.

News

Java performance tuning related news.

A note from this newsletter's sponsor

Java/J2EE performance or scalability problems? Do NOT buy additional
hardware, do NOT buy additional software, do NOT refactor your app.
JTuneTM GUARANTEES improvements with none of the above costs.

Tools

Recent Articles

Jack Shirazi


The Roundup

One interesting discussion was about the fastest way to extract the tokens from a comma delimited string compared three techniques: StringTokenizer, String.split() and a custom search and extraction method. A test showed the custom method fastest, with StringTokenizer 40% slower and String.split() 140% slower. String.split() is, of course, using the new 1.4 regular expression classes, though it doesn't do so the most efficient way.

An interesting discussion was generated on how best to first determine the number of rows in a database when you are also going to subsequently process those rows. The original poster used the sequence

rs.last();
int numOfRowsRetrieved = rs.getRow();
rs.beforeFirst()

moving the scrollable ResultSet to the last row, getting the count, then scrolling back to the beginning row. However, another poster pointed out that many implementations of ResultSet.last() simply iterated through ResultSet.next() until the last row was reached. In fact, that's probably okay if the number of rows is small, since essentially they will be cached for the subsequent processing. But for large result sets, this could be a memory hog. This poster recommended issuing a "SELECT count(*)" query first to get the size of the result set. The original poster suspected that the overhead of this query would be large [though I believe it would be processed in a fairly optimal way by most databases]. Another poster suggested using CachedRowSet. The final poster suggested to build the app first and then tune it, and if the JDBC was a problem then to try it out using each of the options available to find the quickest. Sounds just about right.

JavaGaming.org

A fascinating discussion on whether OutputStream.write() blocks, unearthed some excellent advice. Ultimately, it was pointed out that the behavior of OutputStream.write() is not sufficiently specified. And this probably wasn't an oversight, but actually a consequence of the multiple different specifications on different operating systems, and different configurations. The upshot was that OutputStream.write() could block, though the blocking would be unlikely to be for a significant length of time except in the case where a slow connection was flooded with data, such as a dialup line being written to with lots of data [mind you, that is typical for server writes to slow clients]. Basically, there is no way of guaranteeing non-blocking writes with OutputStream.write(). You need to use NIO writes for non-blocking behavior. And more worryingly, with OutputStream.write() you could get an exception returned rather than having the call blocked, and you need to be able to handle this in high volume writes. If you are handling this situation, bear in mind that a couple of the discussion participants reported that the exception thrown when the OS buffer was overrun was a NullPointerException, and not a type of IOException.

One long rambling discussion started off about the efficiency of the Java collection classes. Generally, these classes can easily produce and discard lots of new objects. Consequently, in tight loops (as you often get in animations), the Java collections can be a liability. Type-specific collection classes were recommended (collection classes which directly hold primitive data types rather than having to wrap those data types). The discussion then went to cover various data structures, and considered the pros and cons of various Java language features (and lack of features). Some of the interesting structures raised were skip lists, which provide a probabilistic way to balance trees; skip ahead lists which basically has shortcuts to specific elements in order to make traversal faster by "skipping ahead" to elements; and parallel arrays which can let you convert arrays of objects to arrays of primitives. It's clear from discussions like these that getting the data structure right goes a huge way to solving any particular problem, including performance problems.

The Server Side

One load tester found client response times growing as he increased the number of simulated clients, but the server was not showing a heavier load. The one responder suggested that the clients were serializing their requests, possibly by reusing the same connection for all clients, which would account for the observations.

A really good discussion on PreparedStatements vs Statement threw up several useful pointers. (Statements are parsed for each call, PreparedStatements parsed once only.) Firstly, if you are not reusing statements, there is no benefit to PreparedStatements. Secondly, for best effect you need to be able to reuse PrepareStatements across connections, and only some drivers support this. Thirdly, PreparedStatements seem to manage arguments better, since quotation need not be considered, parameters are passed to the reused statement as is (except some special consideration may be needed for null parameters).

Kirk Pepperdine.


Javva The Hutt

I went surfing for pleasure. That means I looked at the odd page that particularly interested me, followed random links, and searched for jokes and quotes. And I came across Liudvikas Bukys collection of quotes. This is worth a look if you have and idle moment or two.

There were several gems, not least the explanation of why the US railroad gauage is the size it is. But my favorite, was this brilliant put down of performance consultants (sorry Jack) by Richard M. Romano

I recently had someone evaluate my computer system and make recommendations for improving speed and efficiency, but all he did was make fun of my setup. The mistake was mine: I had accidentally hired an insultant.
-- Richard M. Romano

Not quite in the same league, but still quite good was this page on office and occupational jokes. My favorite here was real quote from a clearly superior manager

We know that communication is a problem, but the company is not going to discuss it with the employees.
(Switching supervisor, AT&T Long Lines Division)

Diary of a Hutt

May 14. Ah, the luxuries of nice beach. A few iced cans of beer, nice blow up chair, soft towel, a good book and kids who know how to play without bothering me. It doesn't get better than this. Of course I brought my laptop along, but can't really do that much on the beach, the screen contrast is too annoying. I have to crick into a really uncomfortable position to see anything, so surfing (the web type) is out. And surfing (the wet type) is out too, since I never got the hang of it.

May 15. Whatever happened to my dreams of retiring by the Sea and writing a novel? If only the dot-bomb hadn't bombed for a few more years, I'd be living my dreams. Ah well, I probably won't be winning the lottery either. Oh yes, I almost forgot, this is my diary on JavaPerformanceTuning.com, so I really need to mention something related to Java performance. Well that's done. Now back to my holiday.

May 23. Smooooth. Lean back on your chair, close your eyes, pretend that there are no troubles anywhere in the world. Just empty your mind completely. Well, hi. Nice of you to join me up here in Nirvana. Some people like active holidays. Some like to just veg out and be at peace with the world. Not hard to guess what I do. Ahhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh...

BCNU

Javva The Hutt.


Question of the month: statics for reuse?

I need to use a StringBuffer to repeatedly build strings. Should I make it static and reuse it?

This question, and varieties of it, is asked a lot. Whenever you are using a temporary object to do some intermediate processing, there is a reasonable temptation to reuse the object where that is possible. For example, the following method uses a temporary StringBuffer to construct a string:

public String sayHello(String title, String name)
{
  StringBuffer s = new StringBuffer();
  s.append("Hello ");
  s.append(title);
  s.append(' ');
  s.append(name);
  s.append(", how are you today?");
  return s.toString();
}

You might think to yourself that each run through this method a StringBuffer is created and thrown away, just to make a String. This seems to be inefficient doesn't it? So what can you do about it? Easy, make the StringBuffer object a static, so that you can reuse it:

private static StringBuffer SayHelloTempStringBuffer = new StringBuffer();
public String sayHello(String title, String name)
{
  StringBuffer s = SayHelloTempStringBuffer;
  s.setLength(0);
  s.append("Hello ");
  s.append(title);
  s.append(' ');
  s.append(name);
  s.append(", how are you today?");
  return s.toString();
}

Hey presto, we have eliminated all those temporary StringBuffers. Great! Well yes and no. It is true that this particular tuning technique is a valid tune. Reusing objects is a recommended tuning technique. But reusing objects is a tradeoff, just like many other tuning techniques. In exchange for reducing the number of objects being used, you now have one very long lived object. You also have the problem that you need to understand StringBuffer internals in order to avoid some subtle effects. For example, a new StringBuffer is created with a default internal char array of a specific size (16). But the static StringBuffer will grow its internal char array to the largest size needed by any of the constructed strings, and that will not get shrunk even if subsequent strings are much shorter. Each constructed String will then use a much larger char array than is necessary, potentially causing huge inefficiencies.

Worse than that is the thread safety of the method. The original method is thread safe, since each invocation uses a StringBuffer object local to the thread. But, although StringBuffer is itself thread-safe, the new "tuned" method is not, since two threads would use the same StringBuffer object, and there are many potential context-switch points between calls to the StringBuffer methods. Methods which are not thread-safe have a tendency to cause bugs sooner or later as changes are made to a program and developers forget that a particular method is not thread-safe.

So is this then a technique to avoid? No, reusing objects in this way is a valid tuning technique, as I said. The problem here is that of premature tuning. Why did we change the method to use a static? Because we thought that all those temporary StringBuffer objects looked inefficient. But one of the first lessons you should learn about tuning is not to guess. Don't guess that there may a performance problem. Implement the code simply, with good coding practices, then measure the performance and find the bottlenecks. If there is a bottleneck, use one of the hundreds of performance tuning techniques available (including reusing objects just like the example above) to improve the performance of the bottleneck. Then document clearly what you've done. (I like to keep the old code in comments.)

The important thing to remember is that you shouldn't anticipate problems which may never occur. Just because some code looks inefficient doesn't mean it will be a problem. The code may in fact be grossly inefficient, but if it is only ever run once or twice it will never matter. Or it may be more efficient than you expect. Or the JVM you run on may be particular good at running that type of code.

Measure performance, and tune identified bottlenecks. Don't guess.

(Note, in case you actually need this tune after having measured that the bottleneck is caused from a temporary and that a static would improve performance: you can avoid the threading issues by making the method synchronized or by using a ThreadLocal object to hold one static reusable object per thread).

The JavaPerformanceTuning.com team


Tips

At JavaPerformanceTuning.com, we scan the internet for any articles with interesting Java performance information. When we find one, we add it to our huge article list, but we also extract the performance tips from those articles, and list those extracted tips in our newsletter. Below, you can see this month's extracted tips.

http://www.javaspecialists.co.za/archive/Issue070b.html
Multidimensional arrays are slow (Page last updated May 2003, Added 2003-07-29, Author Heinz Kabutz, Publisher Kabutz). Tips:

http://www-106.ibm.com/developerworks/java/library/j-jtp04223.html
Performance legends (Page last updated April 2003, Added 2003-07-29, Author Brian Goetz, Publisher IBM). Tips:

http://www.sys-con.com/java/article.cfm?id=1989
J2EE design (Page last updated May 2003, Added 2003-07-29, Author Ajit Sagar, Publisher JavaDevelopersJournal). Tips:

http://developer.java.sun.com/developer/JDCTechTips/2003/tt0624.html
Generating Diagnostics by Monitoring the System Event Queue (Page last updated June 2003, Added 2003-07-29, Author John Zukowski, Publisher Sun). Tips:

http://www-106.ibm.com/developerworks/ibm/library/i-incrcomp/
Incremental compaction in the IBM JDK Garbage Collector (Page last updated June 2003, Added 2003-07-29, Author Aruna Kalagnanam, Sripathi Kodi, Publisher IBM). Tips:

http://www.javaworld.com/javaworld/jw-06-2003/jw-0606-wireless.html
High-availability mobile applications (Page last updated June 2003, Added 2003-07-29, Author Michael Juntao Yuan , Publisher JavaWorld). Tips:

http://www.informit.com/isapi/product_id~{9AA6BD2C-DC80-4583-BEDD-D3930D303F06}/content/index.asp
Concurrency in Java (Page last updated May 2003, Added 2003-07-29, Author Bruce Eckel, Publisher Prentice Hall). Tips:

http://www.ociweb.com/jnb/jnbJul2003.html
Generics in Java (Page last updated July 2003, Added 2003-07-29, Author Rob Smith, Publisher OCI). Tips:

Tips for the week ending 4th July 2003

Continuing from last month's focus on JavaOne presentations, we extract tips from a few more of those presentations this week

http://servlet.java.sun.com/javaone/resources/content/sf2003/conf/sessions/pdfs/1493.pdf
Taking Advantage of the Java 2D API in your Rich Client Application (Page last updated June 2003, Added 2003-07-03, Authors Jim Graham, Shannon Hickey, Chris Campbell, Publisher Sun). Tips:

http://servlet.java.sun.com/javaone/resources/content/sf2003/conf/sessions/pdfs/1402.pdf
Java Technology for Game Developers (Page last updated June 2003, Added 2003-07-03, Authors Chet Haase, Dmitri Trembovetski, Doug Twilleager, Publisher Sun). Tips:

http://servlet.java.sun.com/javaone/resources/content/sf2003/conf/sessions/pdfs/2302.pdf
Detecting and Solving Common J2EE Application Performance Problems (Page last updated June 2003, Added 2003-07-03, Author Charles Palczak, Publisher Sun). Tips:

http://servlet.java.sun.com/javaone/resources/content/sf2003/conf/sessions/pdfs/2165.pdf
Dispelling the EJB Architecture CMP Performance Myths (Page last updated June 2003, Added 2003-07-03, Authors Michael E. Bouchard, Lora C. Wallace, Publisher Sun). Tips:

http://servlet.java.sun.com/javaone/resources/content/sf2003/conf/sessions/pdfs/3588.pdf
Java Technology Design Patterns for High-Load Web Sites (Page last updated June 2003, Added 2003-07-03, Authors Leon Shklar, John Burket, Publisher Sun). Tips:

http://servlet.java.sun.com/javaone/resources/content/sf2003/conf/sessions/pdfs/3420.pdf
Optimizing XML Processing for Performance (Page last updated June 2003, Added 2003-07-03, Authors Rob Ruyak, Lalit Mathwani, Biswadeep Nag, Publisher Sun). Tips:

Jack Shirazi


Last Updated: 2025-01-27
Copyright © 2000-2025 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/newsletter032.shtml
RSS Feed: http://www.JavaPerformanceTuning.com/newsletters.rss
Trouble with this page? Please contact us