Skip to main content

Optimize a Swing App by Slowing It Down

Posted by tball on April 11, 2005 at 4:54 PM PDT

Swing is slow, right? That seems to be a common perception which fast Swing apps like LimeWire seem unable to shake. Even the Jackpot GUI app is sluggish these days, and we all know it cannot be that my code is at fault, right?



I think the real problem is that yours and my computers are too fast, or at least too fast relative to our customers' systems. Because software developers and quality testers tend to have very fast systems so they can multi-task effectively, an unfortunate side-effect is that they tend to run their applications faster than their customers do. As a result, it's easy to overlook inefficient and redundant GUI operations as long as the result looks and feels okay on a fast system. Slow your system down enough, however, and these problems leap out at you, demanding attention.



One easy way to slow down a Swing application is to turn on DebugGraphics functionality. Although DebugGraphics was designed to display potential problems with display painting and layout, it has a nice side-effect of pausing after each paint operation (otherwise you wouldn't be able to see it work). Here is an example of how one might use this:



    private static final boolean debugGraphics = true;
    ...
    if (debugGraphics) {
        DebugGraphics.setFlashTime(100);                 // 100 ms. pause
        DebugGraphics.setFlashCount(1);                  // only pause once per paint
        DebugGraphics.setFlashColor(new Color(0,0,0,0)); // no color

        // turn off double-buffering, or this gets optimized away!
        RepaintManager.currentManager(myComponent).setDoubleBufferingEnabled(false);
        myComponent.setDebugGraphicsOptions(DebugGraphics.FLASH_OPTION);
    }



The first time you run this code, do so in the debugger. If it appears to hang, suspend the app and see where it is stuck. When I first ran it on my app, I had turned DebugGraphics on for my whole component tree -- DebugGraphics was pausing after each bump was drawn on my JSplitPane slider! Not very useful...



Once I only turned debugging on for my main panes, it became painfully obvious that some operations of my apps GUI operations were redundant. My app has a JTable which is supposed to select a JTree node when a row is clicked, but selection was happening multiple times. Setting a breakpoint on my ListSelectionListener showed I needed to first check ListSelectionEvent.getValueIsAdjusting() and only handle the event if its false; failing to do so was causing a new list selection event to be fired for each entry in the tree path for that node (maybe Swing wasn't the problem after all!). These multiple selection events were not that noticeable on my fast system, but after fixing this and other similar problems, the GUI is much perkier.



I am going to leave this code enabled in my app for a few more days. The slow display will irritate me a lot, and so I'll just have to make it faster some other way. Wish me luck!

Related Topics >>