Skip to main content

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
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++) {

    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

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 >>