About a month ago i have introduced the new project named LightBeam that aims to assist look-and-feel writers to measure performance of their libraries under various static and dynamic scenarios. I have used this tool extensively during the performance optimizations of the next release of Substance look-and-feel, and it has now reached its first official release 1.0 code-named Antares.
The project distribution contains sample script files to test static and dynamic scenarios under the core look-and-feels (Metal, Windows and Nimbus), as well as a selection of active third-party look-and-feels (Substance, Looks and Synthetica). The performance spreadsheet available for download contains the breakdown of different scenarios, and here is the “executive summary” for the dynamic scenarios that try to emulate most common user interaction flows:
- 3,039 ms – Metal
- 3,721 ms – Windows
- 4,004 ms – Looks Plastic XP
- 4,696 ms – Nimbus
- 4,794 ms – Substance Autumn 5.0dev
- 4,908 ms – Synthetica default
- 13,146 ms – Substance Autumn 4.3
All the numbers are taken on my main development machine running the latest b26 of 6u10.
Here are some Swing links that you might have missed during this week:
- Jan Erik Paulsen experiments with the new functionality of shaped and translucent windows in 6u10. The screenshots are impressive, and he is correctly pointing out two main deficiencies of the current (semi-private) API. The first is that you need to attach a listener to re-compute the window shape on window resize, and the second is lack of auto soft-clipping on the window shape outline.
- Jan Haderka has announced release 0.9.3 of SwingX. The release notes are available as well, and my only wish is that the official 1.0 release will be before the project turns four years old (next March).
- Dave Gilbert has announced release 1.0.10 of his JFreeChart library.
- Gunnar Sletta writes about release 4.4.0 of Qt Jambi, a Java port of cross-platform Qt client application framework. In addition to supporting all the new Qt features, like Phonon, Webkit, Widgets in Graphics View, XQuery and Qt Concurrent, it also has an improved deployment system, JDBC support and a compile-time checked signal-slot approach.
- Artem Ananiev solicits feedback on the forthcoming JWebPane component. This is a little bit problematic without any kind of downloadable content and no (even preliminary) Javadocs of the current API. Collin Fagan (aberrant) has a few interesting requests in the comments section.
- Jebgeni Kabanov has a screencast on changing the source code of a running Swing application with JavaRebel. Looking at the screencast (is there supposed to be sound), it doesn’t look overly impressive. Most of the changed functionality is available only in a new instance of a form (not in the running ones), and there’s even a glimpse into an exception during the last few seconds of the clip (look in the background Eclipse).
- Andrew Sazonov has a nice utility class for scheduling a delayed invocation of an action listener. This is useful for delaying updating the detail pane as the user scrolls through the master table, or preventing highly dynamic updates of status strings in a progress indicator.
- Finally, there is a lot of interest generated in Greg Brown‘s entry on Pivot, a framework for building cross-platform applications to be deployed on both web and desktop. I concur with Greg that building a new framework on top of Swing and exposing the underlying Swing components is not the best approach, and Pivot builds on top of Java2D instead. There is an interesting comment on Ben Galbraith‘s entry on Pivot that highlights the current trend in RIA toolkits (AIR / Silverlight) – audio / video, animations and skinning.
Here are some Swing links that you might have missed during this week:
- Synthetica look-and-feel has released version 2.7.0 and 2.7.1. No new skins have been added, but there are some new features and bug fixes.
- Swing has aged remarkably well considering its long history and imposed rules of preserving backwards compatibility. However, there are some trends in modern UI design that need some special handling in the application code, and Ken Orr shows how to address a common problem with tree renderers – making them fill the entire width of the row.
- Phoenix addresses a few other shortcomings of Swing components, showing how to provide continuation tooltips on trees and lists, wider and resizable popup windows in comboboxes and more.
- Tim Boudreau announces the availability of a pure tree table implementation available as a standalone module in NetBeans. I have seen a few such implementations, and they usually involve using an entire tree as the rubberstamp renderer for the tree column, translating and clipping the tree to show only the relevant part for each row. This presents significant maintenance problems in passing the events and having look-and-feel consistent animation events. Looks like Tim and Standa Aubrecht have been able to solve these problems. Geertjan Wielenga has a tutorial on how to use this tree table to show information on the file system.
- Collin Fagan continues working on the Swing tutorials and this week he has code samples for trees and borders.
- Alex Potochkin has announced release 3.0 of his JXLayer project. This is one of my favorite third-party additions to Swing, and it’s great to see that it is continuously improving. There is a brand new forum on java.net where you can ask questions on JXLayer, and i have found Alex to be extremely quick to respond and cooperative to address feature requests. We have also updated the Rainbow project to use the latest release of the library.
- David Qiao has posted slides and demo source code for his JavaOne BoF session on working around Swing bugs.
- Anthoney Scotney has announced release 4.2 of WebRenderer Swing edition, a browser SDK based on Firefox 2. The decision to base the code on Firefox is interesting, especially in light of other vendors (such as TrollTech and Sun) deciding to use the competing WebKit library. Firefox 3 is about to be released (perhaps sometime this week), and it would be interestingto see how quicky WebRenderer will switch. The performance improvements in Firefox 3, especially for JavaScript-heavy sites, are quite impressive.
- Joe Conti has created a static analysis tool to detect EDT violations at compilation time. The CheckThread project requires annotating your methods with the name of the intended runtime thread, and then checks to see whether there are any clashes between methods.
- Detangler is another tool that aims to detect Swing threading problems. It attaches to your application running in debugging mode and shows thread-related bugs that cause visual artifacts, gray windows, deadlocks and slow listeners that cause frozen UIs.
- Vaibhav Choudhary proposes a tool that will convert existing Swing applications to JavaFX. I’m not sure if the comparison with GWT as savior to writing AJAX applications is relevant, but from my experience automated conversion from one language to another never results in clean and readable code. There are just too many small differences between any two given languages, and you either decide not to support this (requiring large amount of manual work for any nontrivial app), or end up with an inordinate amount of generated code that doesn’t look anything like the best practices for the target language.
- Finally, Josh Reed has been experimenting with Groovy’s GraphicsBuilder, and he is very impressed.
This post summarizes the changes that were made in Substance 5 to address the performance issues raised by the users. As mentioned before (part 1 and part 2), Substance 5 is 2.5-3.5 times faster than Substance 4.3 on various static and dynamic scenarios. Many thanks go to Dmitri Trembovetski from Java2D team for his help and tips.
- Use multi-stop gradients (LinearGradientPaint) with REPEAT cycle method (as mentioned in the comments on Romain’s blog entry).
- Rendering translucent texts is slow and does not use the new native font rasterizer in 6u10. Solution – instead of installing a translucent composite, interpolate the text foreground color and the background fill color based on your alpha value, and use full opacity text rendering.
- BufferedImage.setRGB and BufferedImage.getRGB are really slow. A custom BufferedImageOp might be more difficult to learn, but is much more performant if done correctly.
- Set RenderingHints.KEY_ANTIALIASING to OFF before calling any Graphics.fill operation that results in aliased fill in any case. This is especially relevant for Graphics.fillRect that gets integer parameters. Java2D is not smart enough (yet) to choose the non-antialiased path when the end result is non-antialiased.
- Intermediate non-cached BufferedImages are slow. Whenever possible, either draw directly on the Graphics context, or collect the final result into one BufferedImage that goes into the cache, even if the cache key is more complex.
- Filling with translucent color or filling under translucent composite is very expensive. In fact, the single largest performance gain (20% of the final result) in Substance 5 was removing watermarks from most core skins.
- Use AffineTransform for rotating painting instead of doing it manually. As with BufferedImageOp, it takes some time to understand how to do it (and i’m still terrible at it), but the performance is much better.
- Use EnumSet and EnumMap whenever possible. This is not Java2D-specific, and the tip goes to Joshua Bloch. These are quite faster than Hash* counterparts.
- Do not do multiplt rendering of the same surfaces. This is especially relevant for tables thatcan have potentially thousands of visible cells on the screen. Try to draw background fills and gradients once per table.
- Last, and not specific to Java2D – profile every scenario, question every method and every line of code.
More tips on Java2D performance right here.
Update: hitting “Submit” too fast, i forgot another Swing-specific optimization. Since everything UI-relates has to run on EDT, you can use non-synchronized non-thread safe code and collections. This comes in quite handy coupled with caching images and additional otherwise guarded blocks.