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 ... 

Question of the month: static objects for reuse 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!


Back to newsletter 032 contents

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


Back to newsletter 032 contents


Last Updated: 2024-11-29
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/news/qotm032.shtml
RSS Feed: http://www.JavaPerformanceTuning.com/newsletters.rss
Trouble with this page? Please contact us