[an error occurred while processing this directive]

Page One
Page Two
The Databank
What Is Swing?
Special Report
IDE Roundup
Swing and the Web
Swing Text
Tech Topics
Friends
Tips and Tricks
The PLAF Papers
Call 911
The Archive
JFC Home
Download Swing
Swing API Docs
Download JDK
JDK Docs
Java Tutorial
 
The Swing Connection Special Report

Performance Secrets in Swing 1.1.1

By Steve Wilson

Performance of Swing-based applications has always been a concern for the Swing team, and each release continues to add performance enhancements. During the transition from Swing 1.0.x to Swing 1.1, the team did a tremendous amount of tuning, which mostly revolved around creating fewer temporary objects during normal operations. The Swing team has now started to turn its attention to reducing the amount of unnecessary painting which occurs. Swing 1.1.1 introduces some new options in the way that Swing handles scrolling and internal frames. This article introduces you to those changes so you can take full advantage of them in your applications.


Scrolling Changes

Under normal circumstances, when a JScrollPane is scrolled, the entire visible contents of the scroll pane are redrawn. This is fine for content that renders quickly, but in some cases it is just too slow. In Swing, much of the work of scrolling is actually handled by JViewport, which is a child of the JScrollPane. JScrollPane is mostly responsible for managing the layout of the viewport and scroll bars.

The Backing Store

Swing has always provided an option to help with this task. The option is called a backing store. You can activate the backing store by calling the method

setBackingStoreEnabled(boolean enabled) 

on JViewport. This technique draws the visible contents of the viewport to an offscreen bitmap and then "blits" part of this image for small scrolls.

This is a very effective technique for small scrolls on complex contents. It is so effective for many JTable tasks that it is automatically activated when a JTable is placed inside a JScrollPane. However, the feature has three major limitations:

First, it isn't as fast as it could be because, for many "normal" operations, two image blits are required instead of one. That's because the contents of the viewport need to be drawn to the backing store, and then copied to Swing's global double buffer. Without the backing store, we can draw directly to the double buffer, avoiding a large amount of bit copying.

Second, because of the way JVieport is currently implemented, the backing store doesn't work when scrollRectToVisible() is called directly by the programmer, or during autoscrolling. This limitation could be fixed with major changes to the internals of JViewport, but the possiblity of causing instabilities outweighs the benefit.

Lastly, it requires considerable extra RAM to maintain this backing store image.

Window Blitting

Given the contraints of the backing store, we've developed another technique that seems to provide better overall performance for most typical applications. This technique is called window blitting. Window blitting is typically used in native windowing systems, such as Win32, MacOS, and X11 to directly move bits from the screen buffer to their new location when scrolling, and to update only the newly exposed region. The java.awt.Graphics class provides a method named copyArea() which is designed to provide this type of functionality. And code has now been added to the JViewport class which can use this technique to improve scrolling performance.

Because this feature is so new, we're currently only exposing it as an option. However, if we don't find major problems, we're likely to make this the default option in a future release. To access this option, you should add the following line of code after you create your JScrollPane:

scrollpane.getViewport().putClientProperty
   ("EnableWindowBlit", Boolean.TRUE);

This should improve scrolling performance in most common applications. However, there are a couple things you might want to be aware of. The most important thing to know is that the current implemenation of Graphics.copyArea makes it difficult for this scheme to work when the JScrollPane is partially obscured by another heavyweight window (such as the Windows NT TaskManager). We currently have code that indirectly detects that case and reverts to a slower algorithm. However, we believe that in typical case when the user is scrolling, the JScrollPane will be in the frontmost Window..


JDesktopPane Improvements

JInternalFrames inside a JDesktopPane have been a sore spot for Swing performance, especially when there are many JInternalFrames, or when they contain complex content such as JTables. To help solve this problem, we've added some code to the DefaultDesktopManager to allow you choose from two options to improve performance.

Outline Dragging

The first option is called outline dragging. This option provides the user with a "ghost frame" when JInternalFrames, are dragged, instead of displaying the full content of the frame being dragged in real time. This alternative offers maximum performance; users typically get a very fast response. To activate this option, you can add the following line of code after you create your JDesktopPane:

desktop.putClientProperty
   ("JDesktopPane.dragMode", "outline");

Another Dragging Option

Outline dragging has been available in previous versions of Swing, and is popular with some users. But many users prefer to be able to see the full content of the frame as they drag. Under the current implemenation of DefaultDesktopManager, the dragging implementation is fairly inefficient, but Swing 1.1.1 has added still another option that can also be used to speed up dragging operations. This new option uses technology similar to the JScrollPane "window blitting" strategy. To activate it, just add the following line of code after you create your JDesktopPane:

desktop.putClientProperty
   ("JDesktopPane.dragMode", "faster");

An Example: The Metalworks Demo

For a more complete example of how to use these option, take a look at the Metalworks demo that ships with Swing 1.1.1. It provides a menu which allows you to switch back-and-forth between these two options. The "faster" drag mode approach suffers the same drawbacks as the JScrollPane blitting option (it doesn't perform well when it isn't the front Window), but we believe it is superior for normal operations. This option will likely become the default option in a future Swing release after it has gotten more testing.


A Note About ClientProperties

Since early versions of Swing, the JComponent "client properties" mechanism has been used in places where more traditional API additions might be used. The options referred to in this article are examples of that. The main reason this is done is to avoid locking down a specific API which might not be appropriate for all circumstances, or because the criteria for a given release does not include "API changes". As these "client property" style features are fleshed out we will likely replace them with more traditional "beans-style" properties in future releases.


Compatibility

The features described in this article will soon be available in the "unbundled" Swing for JDK 1.1 release, and the full JDK release. The following releases will include these features.

  • Swing 1.1.1 (for JDK 1.1.x).
  • JavaTM 2 Java Runtime Environment, Standard Edition, version 1.2.2 (aka JDK 1.2.2).

Conclusion

We hope these improvements will be beneficial to most applications which people are developing with Swing. As mentioned above, some of these options could become the default options in a future Swing release, so we're looking forward to hearing any feedback you have (positive or negative) on these options.


Special Thanks

The Swing team thanks former team member Arnaud Weber for submitting the original code on which the JViewport changes are based.

[an error occurred while processing this directive]