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 by Renaud Waldura.
Permission to make digital or hard copies of part or all of this work for personal
or classroom use is granted without fee, provided that copies are not made or distributed
for profit or commercial advantage, and that copies bear this notice and full citation
on the first page.
Copyright for components of this work owned by others than Renaud Waldura
must be honored. Abstracting with credit is permitted. To copy otherwise, to
republish, to post on servers, or to redistribute to lists, requires prior
specific permission and/or fee. Request permission to publish from
renaud@waldura.com.
Last modified: 2002/08/01 01:17:49 $
|