The Source for Java Technology Collaboration
User: Password:
Register | Login help    

Search

Online Books:
java.net on MarkMail:


Beans Binding 1.1.1 Beats 1.0's Butt, Bigtime

Posted by shan_man on October 19, 2007 at 1:08 PM PDT

I'm pleased to announced that version 1.1.1 of Beans Binding has just been released at http://beansbinding.dev.java.net/. This release provides a drastic increase in performance over 1.0, the addition of support for binding to a JSpinner's value property, and a small set of bug fixes.

Extreme performance gains in this release are the result of a fix made to the BeanProperty and ELProperty classes. As these classes are central to Beans Binding, most things now perform many orders of magnitude faster. Consider the following simple test case, that fetches the value of a property 100,000 times for the same object:


    Person person = new Person("John", "Smith");
    Property p = BeanProperty.create("firstName");
    p.addPropertyStateListener(person, new PSL());

    long start = System.currentTimeMillis();

    for (int i = 0; i < 100000; i++) {
        p.getValue(person);
    }

    System.out.println(System.currentTimeMillis() - start);

In 1.0, this test takes approximately 13,000 milliseconds on my machine. On the contrary, it takes approximately 8 milliseconds in 1.1.1. How's that for bigtime?! You can imagine how applications with many bindings, or components like JTable and JList with large data sets, will perform much better with this version.

I imagine some of you are curious as to how this incredible change in performance was possible. As described in the JavaDoc for BeanProperty and ELProperty, once a listener is installed on the property, values along the paths are cached, and only updated in respose to property change notifications. Knowing that developers are likely to encounter beans that don't fire the correct notifications, and that resulting problems may pose tricky to debug, I began work on allowing developers to turn on a debug option that would have BeanProperty and ELProperty log a message when they detect such a change without notification. They would do this by re-evaluating the entire path on every method call and comparing each object to what they have in their cache. This would, of course, remove any performance gains accomplished by the caching; but only when the debug option is on.

While the toggle for this debug option hasn't yet been added, it turns out that in 1.0 the logic itself was left turned on, only without the messaging—a code path that served only to remove all caching benefits. In 1.1.1 this code path has been turned off pending completion of the debugging feature.

And since we're talking about performance, I'd like to share something else with those of you looking to get every last drop of speed from the current implementation. Naturally you'd expect BeanProperty to perform better than ELProperty for simple paths, since the former avoids the overhead of EL parsing. This will, of course, be true once the implementation has been further optimized. In the current release, however, ELProperty actually performs better in many cases. Consider the following test case that creates a new BeanProperty 100,000 times, and uses each instance to fetch the value for a new object:


    long start = System.currentTimeMillis();

    for (int i = 0; i < 100000; i++) {
    	Property p = BeanProperty.create("firstName");
        p.getValue(new Person("John", "Smith"));
    }

    System.out.println(System.currentTimeMillis() - start);

This test dramatizes the case of an application that creates and binds a large set of bindings, with similar properties, perhaps on the first initializion of a GUI form. In 1.1.1, this code takes approximately 7000 milliseconds on my machine. But replacing BeanProperty with ELProperty reduces it to 330 milliseconds.

Consider this similar test case that uses a single BeanProperty and fetches its value for 100,000 new objects:


    long start = System.currentTimeMillis();
    
    Property p = BeanProperty.create("firstName");
    
    for (int i = 0; i < 100000; i++) {
        p.getValue(new Person("John", "Smith"));
    }
    
    System.out.println(System.currentTimeMillis() - start);

This test dramatizes what JTable or JList might have to do while scrolling, to fetch the value of a single property for a large set of objects. In 1.1.1, this test takes approximately 6900 milliseconds on my machine. Replacing BeanProperty with ELProperty reduces it to 260 milliseconds.

I raise this discussion as a point of interest, not to encourage you to switch to ELProperty (unless your application demands the performance increase that it currently brings). As I mentioned, BeanProperty will be optimized to be the better choice for simple paths. Profiling indicates that the source of ELProperty's higher performance lies with EL's built-in caching of JavaBean BeanInfos—something that can easily be added to BeanProperty.

One final note before I sign off for the weekend: Some of you might ask why the release number has jumped from 1.0 to 1.1.1. The answer is that I actually first released a 1.1, and before I had finished writing up an announcement, internal testing revealed an existing, but previously unknown bug that I thought was worth fixing quickly. Hence 1.1.1. Enjoy!

Related Topics >> Java Desktop      
Comments
Comments are listed in date ascending order (oldest first)