XSLT vs. DOM+ASP performance benchmark

  Goal

  Whenever data, which have to be to be displayed in the presentation tier (ASP, JSP) are in the form of an XML document (example - backend services and/or business logic return data as XML), and the output has to be some sort of (X)HTML, there are two basic approaches to the problem:

  • Creating an ordinary ASP, JSP, PHP, etc. page using DOM to parse data.
  • Using XSLT to transform the XML into (X)HTML. The transformation can be performed in an ASP/JSP page, ISAPI, servlet or CGI using an XSLT transformer like MSXML [*] or Xalan [*].

  Each approach has it's own advantages and drawbacks. XSLT is more flexible and structured approach and permits a level separation of logic and presentation unachievable in ordinary ASP/JSP. On the other hand it requires careful design. Common wisdom tells that the main drawback of XSLT is low performance. There is a notion that XSLT is slower than simple ASP/JSP + DOM because of transformers' poor performance.
  This 'fact' is often quoted as a major drawback of using XSLT in the presentation tier. The following tests reveal that it is not true.

  The Test

  To compare the performance of different server-side approaches to displaying XML documents a sample XML document was used. Different test pages (configurations) were used to display data from the XML file. The output for all configurations was the same, the only difference was in the approach.
  Different ASP pages and a PASP page (used by the MSXML XSLT ISAPI filter) were used. MSXML3 has been used in all ASP pages (no information about the ISAPI filter).
  All tests were done using IIS 5 on Windows 2000 Professional SP2 on an IBM NetVista (PIII 1GHz, 256MB RAM) with Microsoft Web Stress Toolkit running on the same machine. All tests were done for 1, 2, 4 and 8 concurrent clients. The test length was one minute for all configurations.
  Here is a brief description of each configuration:

  • ASP + DOM. An ordinary ASP page using DOM to read data from the XML and print them to the output.
  • ASP + DOM + XSLT (no caching). ASP page using XSLT transformation. The XSLT file is being loaded every time in order to produce the template. XML is passed to the transformer using a DOM object, being initially loaded from a string.
  • ASP + DOM + XSLT (with caching). Same as before, but now the transformation object is saved into a session variable, so there is no need to recreate it on each call.
  • ASP + stream + XSLT (with caching). Same as 'ASP + DOM + XSLT (with caching)' but the XML is passed as a stream (IStream), not as a DOM object.
  • MSXML ISAPI filter. A specific XSLT ISAPI [*] filter, similar to Cocoon [*] in some respects (but inferior in functionality) is used. Version 2.1 of the filter has been used.

  Results

  The value measured is number of calls per minute.
  Results for 1, 2, 4, 8 concurrent clients:

Configuration 1 client 2 clients 4 clients 8 clients
MSXML ISAPI Filter 5549 5481 5507 5512
ASP + DOM + XSLT (no caching) 4756 4721 4709 4669
ASP + DOM + XSLT (with caching) 8685 8610 8502 8448
ASP + stream + XSLT (with caching) 8816 8727 8691 8550
ASP + DOM 8570 8496 8513 8466

  Diagram for the data:


[*]  

  Median results calculated for greater accuracy:

Configuration Result
MSXML ISAPI Filter 5512
ASP + DOM + XSLT (no caching) 4714
ASP + DOM + XSLT (with caching) 8561
ASP + stream + XSLT (with caching) 8696
ASP + DOM 8511

  Diagram for the data:


[*]  

  Conclusions

  The results from the tests reveal that:

  • XSLT is not slower than ASP+DOM in this test.
  • Caching the stylesheet/template greatly improves performance. I must be perceived as mandatory for any performance-demanding applications.
  • The MS ISAPI XSLT filter has a poor performance.
  • Using a stream for 'printing' directly to the output slightly improves the performance.
  • All configurations scale linearly (the cached template object is multi-threaded).

  The tests have a limited scope and when considering the results, the following factors must be taken into account:

  • The XSLT transformation used required the transformer to read the entire XML first. In some cases this could be avoided. It could potentially lead to higher performance.
  • The XML document and the output are relatively small. The performance patters may be affected by the size of XML data and the complexity of transformations performed.
  • XPath has been used in the ASP+DOM configuration. Avoiding the use of XPath may lead to higher performance in certain situations.

  So, the overall conclusion is that XSLT can be used easily from dynamic web pages and must be taken into consideration as a viable option. The performance penalties are not very big, at least in some cases. Simple measures must be taken in order to ensure good performance.

  Test data and output

  The XML document used for the test is:


<document> <hours> <loc>ABQ</loc> <strt_dte>MAR-17-94</strt_dte> <end_dte>DEC-31-11</end_dte> <open_24_hrs>N</open_24_hrs> <clsd_ret_ok>N</clsd_ret_ok> <day num="0"> <hrs_open>08:00A</hrs_open><hrs_cl>05:00P</hrs_cl> <hrs_open2>06:00P</hrs_open2><hrs_cl2>08:00P</hrs_cl2> </day> <day num="1"> <hrs_open>08:00A</hrs_open><hrs_cl>05:00P</hrs_cl> <hrs_open2>06:00P</hrs_open2><hrs_cl2>07:00P</hrs_cl2> </day> <day num="2"> <hrs_open>08:00A</hrs_open><hrs_cl>07:00P</hrs_cl> <hrs_open2>08:00P</hrs_open2><hrs_cl2>09:00P</hrs_cl2> </day> <day num="3"> <hrs_open>08:00A</hrs_open><hrs_cl>05:00P</hrs_cl> <hrs_open2>06:00P</hrs_open2><hrs_cl2>08:00P</hrs_cl2> </day> <day num="4"> <hrs_open>08:00A</hrs_open><hrs_cl>05:00P</hrs_cl> <hrs_open2>06:00P</hrs_open2><hrs_cl2>08:00P</hrs_cl2> </day> <day num="5"> <hrs_open>08:00A</hrs_open><hrs_cl>05:00P</hrs_cl> <hrs_open2>06:00P</hrs_open2><hrs_cl2>07:00P</hrs_cl2> </day> <day num="6"> <hrs_open>08:00A</hrs_open><hrs_cl>05:00P</hrs_cl> <hrs_open2>07:00P</hrs_open2><hrs_cl2>07:30P</hrs_cl2> </day> </hours> </document>

  The output html, generated by all configurations, can be seen here [*]

  Source files

  Here is a description of all files [download source] used for implementing the abovementioned configurations:

File Description
gethours.pasp Configuration using the MSXML XSLT ISAPI filer.
gethours-classic.asp ASP + DOM configuration.
gethours-IE5.xsl XSL used for all XSLT configurations.
gethours-xslt.asp Used in all XSLT configurations. Please pay attention what changes must be done in order to change configuration (below).

  A small extract from Gethours-xslt.asp. Pay attention to comments in order to change the file so that it works in different configurations.


<%@LANGUAGE="JavaScript"%> <% Response.expires=-1; function loadSource(strXML) { // The following code is for ASP + DOM + XSLT //var xmlDoc=new ActiveXObject("MSXML2.FreeThreadedDOMDocument"); //xmlDoc.async=false; //xmlDoc.loadXML (strXML); //return xmlDoc; // The following code is for ASP + stream + XSLT var xmlStream = new ActiveXObject("ADODB.Stream"); xmlStream.Open (); xmlStream.WriteText (strXML); xmlStream.Position = 0; return xmlStream; } function getProcessor(transformName) { // To disable caching, just change // to 'if (true)' if ("" + Session(transformName) == "undefined") { var xslDoc=new ActiveXObject("MSXML2.FreeThreadedDOMDocument"); var xslTemplate=new ActiveXObject("MSXML2.XSLTemplate"); xslDoc.async=false; xslDoc.load(Server.mapPath(transformName)); xslTemplate.stylesheet=xslDoc; xslProcessor=xslTemplate.createProcessor(); Session(transformName)=xslProcessor; } else { xslProcessor=Session(transformName); } return xslProcessor; } function transformData(srcDoc,processor) { processor.input=srcDoc; processor.output=Response; processor.transform(); return true; } function main() { var srcDoc=loadSource (the XML goes here); var processor=getProcessor("gethours-IE5.xsl"); transformData(srcDoc,processor); } main(); %>