logo

Java Performance Tips

Use StringBuffer for string concatenation

Because Java Strings are immutable, usage of the + operator to concatenate strings results in the creation of many temporary objects. Calling explicitely StringBuffer.append eliminates those temporary objects and may result in a large performance increase.

I also tend to believe it is simply more correct to use StringBuffer.append when concatenating strings, rather than the + operator. But maybe your reason is because it's faster than String.+ !

Buffer your I/O

I/O operations in Java are by default unbuffered. This means that every single byte written to a stream is passed to the operating system and flushed to disk. This is by design, but incredibly inefficient. A common Java idiom is to explicitely insert a buffering class following the Decorator pattern:

InputStream is = new BufferedInputStream( new FileInputStream(f) );

This improves performance a lot, but there's a better and easier way, simply by buffering data yourself. It depends on your application whether this is easy to do or not, but usually it is simply a matter of declaring a local buffer and using buffered I/O operations.

InputStream is = new FileInputStream( f );

byte[] buffer = new byte[length];
int l = is.read(buffer, 0, length);

if (l != length) // some sort of problem here

Numbers quoted during the JavaOne 2001 conference give Java-buffered I/O as being 100x faster than basic I/O, while explicitely buffered I/O could be up to 500x faster. Quite substantial!

Virtual Machine Modes

As of JDK 1.3, the Sun JVM understands the options -classic, -client and -server.

classic
disables the Hotspot JIT compiler.
client
activates the Hotspot JIT for "client" applications. Client apps are defined as having a short lifespan, and requiring very fast response times.
server
activates the "server" Hotspot JIT: it requires a fair amount of time to warm up, but delivers best performance, similar to native code in most cases.
The -server flag enables all kinds of sophisticated optimizations usually found in static compilers (C, Fortran), including but not limited to:
  • Range check elimination
  • Common Subexpression Elimination
  • Loop invariants
  • Function inlining
  • Loop unrolling
  • see the references for more
For most applications, the Java platform 1.3 is said to finally be on equal footing with static languages.

Garbage Collection

The garbage collector has been greatly improved: creating a new object is now an incredibly cheap operation, in most cases equivalent to shifting a pointer in memory. Don't necessarily be afraid of creating many short-lived objects, they will be garbage-collected very efficiently.

Finalizers impact performance very badly: they force two passes of GC. Code making use of finalizers can be up to 60x slower! Weak references can be used instead of finalizers when this kind of behavior is needed.

Don't call java.lang.System.gc(): it forces a full GC when probably not needed. GC is meant to be asynchronous, let it be that way.

Sun's 1.3 VM and later offers an "pauseless" (incremental) garbage collector. It is said to do away with most GC-induced pauses. Give it a try by invoking the VM with -Xincgc.

Object Pooling

Don't do it. Outside of some rare cases where you are actually pooling the resource held by the object and not the object itself (e.g. thread pools, database connections, huge bitmaps, etc.), object pooling is not worth doing anymore. Object allocation is now so fast that the necessary synchronization required by an object pool implementation is slower than simply allocating new objects.

References

JDC Tech Tip: String vs. StringBuffer
JavaOne 2001 session #573: Java Performance (Steve Wilson, Scott Oaks, Brian Doherty)
Also talks about java.nio for memory-mapped I/O.
How to improve Java I/O performance by Nick Zhang
The Java HotSpot Virtual Machine
More information about the Client and Server VMs.
Frequently Asked Questions about the Java HotSpot Virtual Machine
How to apply the new VMs to specific problems.
Tuning Garbage Collection
Get better performance by tuning the garbage collector.


Copyright © 2000-2007 Renaud Waldura <renaud@waldura.com>