[9 July 2012]
A couple of weeks ago, I took some time to explore the use of sub-forms in XSLTForms, as a possible way to speed up an XForm I had written that was a little slower than I would have liked.
The short version of the story is: WOW! Well worth learning to use.
To understand the longer version, dear Reader, you should know that one of the most common performance issues in serious uses of XForms is that forms sometimes slow down when the instance documents they are working on get big. I assume this is because browsers are profligate with resources, perhaps because some aspects of the XML DOM force them to be, perhaps because profligacy pays off most of the time. But I can’t say I really know for sure.
So one of the things that sophisticated users of XForms spend a lot of time on is finding ways to avoid loading all the instance documents at once. (This is a lot easier when you’re using an XML database as a back end, of course.) Another is finding ways to avoid loading all of the form at once; that is where sub-forms come in. The word doesn’t occur in the XForms 1.1 spec, but a number of implementations provide experimental support for sub-forms as an extension. The basic idea is that whenever certain events occur in a form, the XForms implementation will load some appropriate resource specifying some XForms widgets and bind them into the current form. When other events occur, those widgets will be unloaded again. I first saw this in a demo on the BetterFORM site a few years ago, but I see that Mark Birbeck was talking about this as long ago as 2006. And more recently, Alain Couthures has added sub-form support to XSLTForms.
Making my form use a sub-form turned out to be simpler than I had feared. I already had a full working version of the form, and it was clear which part of it I wanted to load and unload dynamically. What I had to do was just:
- Move the part of the form that should load dynamically (which I’ll now call the subform) into a separate XHTML + XForms document. Give it a simple XForms model, and check to make sure that it works by itself. (It doesn’t actually have to work by itself, but it’s helpful to know the subform hasn’t got fatal errors on its own.)
- In the main form, put an XForms
xf:groupwhere the sub-form used to be; give that group an ID.
- Associate a
loadaction with the appropriate event. (In my form, I had a trigger that toggled a switch, exposing the read/write view of some material. The sub-form now has that read-write view, and the trigger now throws a
- Associate an
unloadaction with another appropriate event. (In my form, this was the trigger that formerly toggled the switch back to the read-only view.)
In principle, that’s it, though I had to fiddle a bit to make everything work right. In particular I ended up adding a
ref="." attribute to the outermost
xf:group in the sub-form. I’m not yet sure just when this is necessary and when it’s not.
The simple example of sub-forms loading on the XSLTForms web site is very helpful here: it’s a very simple example and illustrates all the moving parts clearly. (But you will need to read the source and think about what is going on; there isn’t a lot of commentary or documentation around.)
What really impressed me were the effects of this change on the performance of the form.
Since sub-form support was added fairly recently to XSLTForms, I had to upgrade from an older release of XSLTForms to the recent release 1.0RC. I did some fairly tedious timings before and after I made the change, and I can say with some evidence that this change alone gave my form about a 25% increase in speed. Then I made the changes mentioned above, to use sub-forms. That gave me another 25% increase, so that on almost all actions version 1.0RC using sub-forms was about twice as fast as the older version Beta3 using a monolithic form.
Moral 1: If you are having performance issues with an XForm, and you can see how you might use a sub-form, then try it.
Moral 2: If you are having performance issues with an XForm, and you are using XSLTForms, then try moving to 1.0RC even if you can’t see how to use a sub-form in your context. Alain Couthures has done a lot of work on performance, and it clearly helps.
Bear in mind that the precise syntax and semantics of sub-forms are a topic of discussion in the XForms working group, so (a) they are subject to change, and (b) the working group is open to suggestions for making sub-forms (or any other part of XForms) work better.