Tapestry Training -- From The Source

Let me help you get your team up to speed in Tapestry ... fast. Visit howardlewisship.com for details on training, mentoring and support!

Thursday, November 02, 2006

Improve Tapestry performance with tapestry-prop

I've just deployed a new version of the tapestry-prop library for Tapestry 4.0. tapestry-prop adds a new binding prefix, "prop:", as an alternative to "ognl:". The actual moving of property values is accomplished using runtime generated bytecode, which performs better than OGNL's use of reflection.

The major new feature is support for property paths. You may now uses a series of property names, i.e., user.name. This vastly extends the usefulness of the "prop:" binding, since is can be used in about 90% of the places you'd normally use "ognl:".

The lack of reflection means that "prop:" peforms almost exactly the same as pure Java code. Based on some cursory performance testing, we're looking at a 27x improvement. In a typical Tapestry page, I suspect this may add up to a millisecond or so per request.

The version number has been changed to 1.0.0-snapshot. tapestry-prop should work with JDK 1.3 (Tapestry's minimum requirement).

If you were paying attention during the screencast, you'll note that an even more powerful version of this code is the default binding prefix in Tapestry 5.

16 comments:

Anonymous said...

On the tapestry-prop page there is a statement that reflection is still 5-10 times as expensive as a normal method call. In fact, in java 5, the premium is supposed t be 30%. Not insignificant, but not that big a deal either, if the method is doing anything.

Colin Sampaleanu

David Channon said...

We are still using Tap 3.x (350+ pages in one of our apps) and it would be great if this could be back ported to Tapestry 3.x . Are there any major problems (other than just doing it) for this to occur?

Howard said...

I know the number has been trending down; getting to be a 30% penality is pretty amazing. Every time I've tried to benchmark it, it's been in the 5x to 10x range; you can see it in the chart, comparing OGNL (reflection) to pure Java (no reflection), the difference was significant.

In terms of backporting this to 3.x ... 4.0 was architected for this kind of extensibility; that was the whole point. This could be hacked into 3.0 but its a major amount of work.

Anonymous said...

That's very good news indeed. Was thinking about doing it myself but you beat me to it -:).

What would be be a welcome addition is if tapestry-prop could work with Maps, so I could use "prop:components.mytable.tableRow.NumberOfBids" ( currently it says Class java.util.Map does not contain a property named 'mytable'. ) What do you think about that ?

Anonymous said...

... and just one more thing : I often use BigDecimal to store financial data with the translator="translator:number" in @TextField. I _suppose_ that either translator or @TextField use java.lang.Long internally. Either way ognl was able to automatically convert it to BigDecimal, but when I use prop: instead of ognl: I get "java.lang.Long cannot be cast to java.math.BigDecimal" exception. Can prop take on this data coersion for the sake of backward compatibility,or should we modify the translator ?

Anonymous said...

Is it compatible with Tapestry 4.1.1?

Howard said...

It should be compatible with 4.1.1.

In terms of Maps ... why not just use OGNL for those cases?

Tapestry 5 is much smarter about data type coercions; the Tapestry 4 APIs do not provide the necessary information to do things automatically (you can't ask a binding what the target property's type is). OGNL picks up the slack. A custom translator, for BigDecimal, may be necessary.

Peter said...

Howard, I think the tapestry-prop extention is a great enhancement, but could you perhaps make it available as a library with a simple half a page set of instructions on when to use it and how to install it. Looking through your repository is too confusing for me, I would love to try it but I am not sure what I am looking at or what I have to do to use it.

Thanks
Peter

Anonymous said...

Why you remove AspectJ from Tapestry5?

Anonymous said...

There is one small limitation in terms of using this prop: binding (as Tapestry 4.0.2):

You can not access properties defined in the page/component template or in the page/component specification. It is always seen like a java.lang.Object.

If you need a different type (anything but java.lang.Object) then you have to define (abstract) accessor method(s) in the java class for it (though might not be used at all inside the java class but just in the template or page/component specification).

Is it possible to somehow extend the 'property' element of the page/component specification to declare the type ?

Howard said...

Just change <property name="foo> in the XML file to public abstract MyType getFoo(); in the Java code. Tapestry will create a transient read/write property automatically. The <property> element is for when you don't know or care about the type of the property (and works great with OGNL).

Peter said...

Is there a version compatible with 4.1?

Howard said...

I haven't tested this with 4.1, but there does not seem to be any changes to the IBinding or BindingSource interfaces, so I expect this to be compatible.

nirvdrum said...

I have to agree with the request of making tapestry-prop work with properties defined in the page spec. Realistically, I don't care about the type -- tapestry-prop does, and having to work around it by adding essentially useless code to the page class is not a very nice solution. Moreover, tapestry-prop is not a drop-in solution, since I'd have to rearrange a bunch of code to really make use of it.

Howard said...

Tapestry-prop isn't designed to be a drop-in replacement for OGNL. It's supposed to work for 90% of the cases, but the last 10% belong in either Java code or OGNL expressions.

The reason it doesn't work for elements defined in the XML is because the type of those objects is java.util.Object. Here you see the evolution of code and ideas ... there was no advantage to defining, in the XML, the type of the property, since it would only be accesed using OGNL, which doesn't care about property types, just about actual classes. Then tapestry-prop comes along which does care about property types ... we'll, this is an example about why I've gone the Tapestry 5 route, as an escape from all that baggage, all those prior ideas working at odds to each other.

Albert said...

Do I understand correctly that the OGNL processing is done only on page compilation ? I.e. if I already have the compiled page in the pool, the OGNL performance is irrelevant ?