Wednesday, March 28, 2007

XSLT via Smooks - Comparisons

As you may already know, JBoss ESB uses Smooks to perform message transformation. One of the design goals of Smooks is to support fragment based transformations i.e. targeting transformation logic at a fragment of an XML message/document as opposed to the whole message. The good thing about this approach is that it not only means you can perform more componentization of your transformation logic, but it also means (often more importantly) that you can easily mix and match different types of transformation logic (XSLT, Java, Groovy, StringTemplate etc) within the context of a single message transformation. This is a very powerful feature. From a purely XSLT perspective, this also means you can have functionality equivalent to XSLT Extensions (Xalan Extensions), but maintain portability across XSL Processors.

I recently performed some performance profiling of Smooks based XSL transforms, comparing them against standalone XSLT. This was done in order to get a better idea of the overhead incurred by using Smooks to perform XSL based transforms. I'll attempt to answer the question of why you'd bother applying XSLT via Smooks in future blog.

The comparisons were run on a Dell Latitude D820 (2GHz Dual Core), 2 GB of RAM, running Windows XP, running jdk1.5.0_10.

For this round of comparisons (I hope to do more some time in the future):
  1. I selected a very simple message format (an with multiple ), as well as a very simple set of XML to XML transformations to be performed on that message. I wanted to keep it simple in order to keep the resulting XSLTs as simple as possible. This way I hope I can get a "worse case scenario" re the overhead incurred while using Smooks to perform XSL transforms. The tests are available here.
  2. I compared the number of messages transformed in a 6hr time period.
  3. I compared the results produced by using the following XSLT processors: Sun XSLTC (JDK 1.5), Xalan 2.7.0, Saxon 8.7.
  4. I compared the results produced by a DOM Source and Result for XSLT Standalone versus a DOM Source and Result on Smooks.
  5. I compared the results produced by streaming both the Source and Result for XSLT Standalone versus a DOM Source and Result on Smooks (Smooks only supports DOM based XSLT).
  6. I tested against 10 input messages ranging in size from 20K to 200K. That is, 10 threads running concurrently, continually transforming, each pausing for 10ms between iterations.
  7. The message bytes were read and buffered in memory so as to avoid File IO variabilities.
  8. During the timed test runs, I didn't compare the transformation output against the expected output. However, I did perform preliminary test runs on all processors and verified that the output produced across the board was consistent. The one exception to this was Xalan 2.7.0, which has a concurrency bug that results in the transformed output not being consistent when the XSL is not applied in a synchronized fashion. I still ran the tests against Xalan unsynchronized, so as to get an idea of how it would perform, assuming the absence of this bug.
The test results (listed below) clearly show that streaming XML into an XSL processor makes a huge difference in terms of throughput. The fact that streaming is faster did not surprise me, but the extent of the difference did. In some cases the whole process (taking the input stream, transforming it and producing the output stream) was up to 4 times faster than the poorest performing alternative (taking the input stream, paring it to a DOM, transforming the DOM to a DOM using the XSL Transformer and finally serializing the resulting DOM to the output stream).

In summary, the performance figures are as follows....

DOM based XSLT Vs Smooks based XSLT (also DOM based):



Total Bytes - XSLTTotal Bytes - Smooks/XSLTSmooks Relative Performance
Sun XSLTC709530946565995260892884.50%
Saxon 8.7319880472482987463103293.39%
Xalan 2.7.0400900381203857131051296.21%




(full details)

Stream based XSLT Vs Smooks based XSLT (DOM based):



Total Bytes - XSLTTotal Bytes - Smooks/XSLTSmooks Relative Performance
Sun XSLTC2237761892165995260892826.79%
Saxon 8.71464828944402987463103220.39%
Xalan 2.7.0863166141363857131051244.69%




(full details)

To understand what this means for JBoss ESB Transformation, you first need to understand what it means for Smooks. At the top of this blog I mentioned how Smooks implements a fragment based approach to message transformations (including some of advantages of that approach). The down side to this fragment based approach is that Smooks currently supports this via a DOM based model.

So what does all this mean for JBoss ESB Transformation. Well, because JBoss ESB Transformation relies on Smooks to manage and apply transformation logic (including XSL transforms), it means that JBoss ESB cannot currently avail of the performance advantages offered by streaming messages into an XSL Processor. So, for a transformation where you don't need to features offered by Smooks (fragment based transforms etc) and you want to implement the transformation in XSLT, the performance hit is quite significant.

Luckily, this is not all that difficult to work around for JBoss ESB because we can simply implement a native XSLT ActionProcessor that can apply XSLTs using streaming. This is just a couple of lines of code - no big deal. From a Smooks perspective, there's a little bit more involved, but I don't think all that much. In short, Smooks could simply check the resources targeted at the message exchange in question, and if there's only one, which is targeted at the "docroot" fragment, and it's a stream supporting resource, then stream it - no need to DOM'ify. This would enable JBoss ESB to have the best of both worlds again... stream based XSLT + management and exchange based selection of transformation resources (via Smooks). We'll keep this for another blog :-)

2 comments:

ert said...

Ha! I beat Mark to leaving the first comment. Nice read Tom. I really like the fragment approach, having written some huge XSLTs in the past. I think one of the most attractive benefits for me is re-using the fragments in other transformations. That could have saved me a lot of time. I'd like to see a "best-case-scenario" test where the XLST gets really hairy, i.e. due to lots of normalization in the XML which makes you have to loop and jump, as that would be much easier to implement (and probably better performing) using Smooks. Maybe we can do this for a real world scenario, if any of our users is interested in some transformation optimization.

Another thought I had that fragment processing may lend itself better to utilize the power of multiprocessor machines?

Tom Fennelly said...

Sure thing Kurt.... comparisons based on a more complex transformation scenario are something I do plan on doing.

As I said, I purposely chose the message format and transformation so as to favor XSLT. Any XSLT processor should be able to perform that transform in a single pass.

As the transformation gets more hairy, I'd expect the advantages of streaming the message to fall off - I've yet to prove that more formally however :-)

The streaming approach also has the downside of it being a one-shot-transformation-solution. You need to be able to do all your transformation within a single application of the XSLT.