Chapter 1. Introduction

The trouble with doing something right the first time is that nobody appreciates how difficult it was.

Fortune

There is a general perception that Java programs are slow. Part of this perception is pure assumption: many people assume that if a program is not compiled, it must be slow. Part of this perception is based in reality: many early applets and applications were slow, because of nonoptimal coding, initially unoptimized Java Virtual Machines (VMs), and the overheads of the language.

In earlier versions of Java, you had to struggle hard and compromise a lot to make a Java application run quickly. More recently, there have been fewer reasons why an application should be slow. The VM technology and Java development tools have progressed to the point where a Java application (or applet, servlet, etc.) is not particularly handicapped. With good designs and by following good coding practices and avoiding bottlenecks, applications usually run fast enough. However, the truth is that the first (and even several subsequent) versions of a program written in any language are often slower than expected, and the reasons for this lack of performance are not always clear to the developer.

This book shows you why a particular Java application might be running slower than expected, and suggests ways to avoid or overcome these pitfalls and improve the performance of your application. In this book I’ve gathered several years of tuning experiences in one place. I hope you will find it useful in making your Java application, applet, servlet, and component run as fast as you need.

Throughout the book I use the generic words “application” and “program” to cover Java applications, applets, servlets, beans, libraries, and really any use of Java code. Where a technique can be applied only to some subset of these various types of Java programs, I say so. Otherwise, the technique applies across all types of Java programs.

Why Is It Slow?

This question is always asked as soon as the first tests are timed: “Where is the time going? I did not expect it to take this long.” Well, the short answer is that it’s slow because it has not been performance-tuned. In the same way the first version of the code is likely to have bugs that need fixing, it is also rarely as fast as it can be. Fortunately, performance tuning is usually easier than debugging. When debugging, you have to fix bugs throughout the code; in performance tuning, you can focus your effort on the few parts of the application that are the bottlenecks.

The longer answer? Well, it’s true that there are overheads in the Java runtime system, mainly due to its virtual machine layer that abstracts Java away from the underlying hardware. It’s also true that there are overheads from Java’s dynamic nature. These overhead s can cause a Java application to run slower than an equivalent application written in a lower-level language ( just as a C program is generally slower than the equivalent program written in assembler). Java’s advantages—namely, its platform-independence, memory management, powerful exception checking, built-in multithreading, dynamic resource loading, and security checks—add costs in terms of an interpreter, garbage collector, thread monitors, repeated disk and network accessing, and extra runtime checks.

For example, hierarchical method invocation requires an extra computation for every method call, because the runtime system has to work out which of the possible methods in the hierarchy is the actual target of the call. Most modern CPUs are designed to be optimized for fixed call and branch targets and do not perform as well when a significant percentage of calls need to be computed on the fly. On the other hand, good object-oriented design actually encourages many small methods and significant polymorphism in the method hierarchy. Compiler inlining is another frequently used technique that can significantly improve compiled code. However, this technique cannot be applied when it is too difficult to determine method calls at compile time, as is the case for many Java methods.

Of course, the same Java language features that cause these overheads may be the features that persuaded you to use Java in the first place. The important thing is that none of these overheads slows the system down too much. Naturally, “too much” is different depending on the application, and the users of the application usually make this choice. But the key point with Java is that a good round of performance tuning normally makes your application run as fast as you need it to run. There are already plenty of nontrivial Java applications, applets, and servlets that run fast enough to show that Java itself is not too slow. So if your application is not running fast enough, chances are that it just needs tuning.

Get Java Performance Tuning now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.