It's no secret that today's Java is performance-challenged. Although a number of advances have been made in the past year, including the availability of just-in-time (JIT) compilers for all of the major platforms, many performance issues remain. (For more on improving Java performance, see the optimization article in the April issue of JavaWorld.)
Why it's not up to snuff: A look at Java's performance problems and work-arounds
Java's performance problem spawns two major side effects: Developers whose applications require performance greater than can be achieved currently with Java are sometimes forced to select a different programming language, with native execution; and, programmers using Java often will choose programming strategies that are perceived as faster, sacrificing good programming practices such as encapsulation, object-oriented design, and thread safety.
Java's slowness is not merely a result of it being an interpreted language. There are some language features (dynamic method invocation and synchronization, for example) that are slow, even when using compiled Java. Sun's new Java virtual machine (JVM) strategy will address these problems.
Straight from the horses' mouths: Two Sun engineers discuss peformance
At this year's JavaOne Worldwide Developer Conference, held April 2-4, in San Francisco, two engineers from Sun Microsystems discussed "high-performance Java" (in a technical session of that title) from two different angles. Peter Kessler started the session by explaining some of the common programming "mistakes" that result in performance hits.
Kessler discussed several very common characteristics of slow code, including a number of Java-specific issues that are pretty well known. Kessler's recommendations included:
Choose a good algorithm. Don't pick something ad hoc if a little research can reveal an algorithm that could save a lot of time. An aside to this point was that it is important to learn the entire Java library so you are aware of the functions that will buy you the best performance. (For example, if possible use
System.arraycopy(), and use
System.currentTimeMillisfor timestamps versus a new Date object.) Also, try to know the algorithms of the existing class libraries. Java's HashTable, for example, is not very efficient for long strings that have similar prefixes (like URLs that start with "http://www."), since it only hashes on the first eight or nine characters!
Use the abstract windowing toolkit (AWT) efficiently. For example, don't paint regions you know are going to be outside of the clipping region.
Put debugging flags around calls to construct and print debugging information, rather than putting them inside a debugging function that has to be called whether you are debugging or not.
Use "Buffered" input and output streams. Kessler stressed that this is particularly effective for input streams.
All of the above performance techniques require the programmer to take action to avoid creating the wrong code, and to know how to apply the right code in the right situations. This is good, but Sun says it can do better.
Why JITs aren't the perfect solution
JITs can speed up the execution of basic type operations (for integers, floating point, and so on) and some compute-intensive tasks, and these compilers have been found to significantly improve Java execution.
Although JITs are very popular today, they don't solve all of the problems of Java performance. JITs compile the code on-the-fly and don't have time for any significant optimization. They also don't have much effect on the performance of operations like dynamic method invocation, slow garbage collection, and very slow thread synchronization. These problems force programmers to use
final methods, avoid synchronization, and reduce the creation of temporary objects to get around a lot of garbage collection.
In actuality, many of these approaches have no significant affect on the program's performance. (Use a profiler, like the one built into the standard Java interpreter, to determine the program's weak spots. They are almost never intuitive.) But there are some legitimate techniques for speeding up Java programs. Whatever the technique, however, the result is that developers are avoiding good programming practices and producing classes that are hard to reuse and hard to maintain.
Aah, that hits the (performance) spot!
David Griswold, the other Sun Microsystems engineer at JavaOne's "High-Performance Java" technical session, discussed Sun's new Java virtual machine implementation. This new design takes the JVM to a new level, incorporating a number of new technologies Sun believes will result in Java program speeds that match speeds of native executables. This JVM technology is being developed by Sun under the name "Project Hot Spot."
The new JVM design should overcome all of the remaining problems not solved by JITs. Static compilers that generate native code from Java also will have some remaining problems. Griswold said Sun has been doing extensive analyses of Java program execution. Its research has revealed traditional optimization (like the optimization that would ordinarily be done by JITs) works poorly for object-oriented programs with smaller objects, smaller functions, and more function invocations. This kind of optimization will never reach the performance levels of typical C++ programs.
"Hot Spot" uses a technique called "adaptive optimization" to analyze a Java program as it is loaded and to find the critical "hot spots" in the code (those sections that will execute most often and most slowly if not optimized). This buys time for more significant optimization than that provided by today's JITs because the "Hot Spot" VM can spend more time on less code. Also, because optimization is done at run time, more information is available than would be during static compilation, resulting in better optimization decisions.
The garbage collector also has been improved using a combination of techniques. One technique is called "fully generational copying with scavenging of short-lived objects," which improves the performance of allocation and deallocation of lots of temporary objects (as encouraged by the Java language and libraries).
Another technique is "non-disruptive (soft real-time) incremental collection of long-lived objects." This means that the garbage collector will be able to do much of the garbage collector process in a thread executing asynchronously with the other program threads. This is different from the current implementation that does its garbage collection as an autonomous process, actually pausing the rest of the program for a noticeable period. The new garbage collection process will have no noticeable delays.
Finally, the new "Hot Spot" VM will incorporate a brand new synchronization algorithm. Sun did not talk about the details of this new breakthrough except to say that synchronized blocks and methods will be "many, many times faster," to the point that they are "almost free." This is good news, since synchronization is such an important part of the Java language.
The new "Hot Spot" VM should be available in the fourth quarter of this year, but in the next few months, Sun also hopes to make available a preview release of the technology. In the mean time, if you are developing applications that you plan to use and maintain into the next year and beyond, I recommend you concentrate on the obvious performance challenges and stay within the bounds of good object-oriented design. If Sun lives up to its promises, there will be no better language choice than Java.
Learn more about this topic
- http://www.javaworld.com/javaworld/jw-04-1997/jw-04-optimize.html Article by Doug Bell on optimization and performance issues.
- http://www.javasoft.com/javaone/track1.html#perf This is the url to the session info that I attended.