Author: Pankaj Kumar
e-mail: pankaj_kumar@acm.org
Date: September 30, 2001
Software environment consisted of:
// Code for illustration only. Won't compile. for (int i = 0; i < loopCount; i++) { System.gc(); long startMem = Runtime.totalMemory() - Runtime.freeMemory(); long startTime = System.currentTimeMillis(); result = process(); // Do the processing. long endTime = System.currentTimeMillis(); long endMem = Runtime.totalMemory() - Runtime.freeMemory(); memUsed[i] = endMem - startMem; elapsedTime[i] = endTime - startTime; }
Both Crimson and Xerces parsers were used for the measurement. To use Crimson parser, crimson.jar was kept in .\lib directory. Similarly, to use Xerces parser, xerces.jar was kept in .\lib directory. Note that the run.bat, used for kicking-off the execution run, took jar files from .\lib.
Following precautions were taken while making the measurements:
Five different input files, labelled as TINY, SMALL, MEDIUM, BIG and HUGE, were used. Their characteristics are shown in the table below:
Label | rxgen arg. | Filesize |
---|---|---|
TINY | 20 | 9KB |
SMALL | 200 | 72KB |
MEDIUM | 2000 | 719KB |
BIG | 20000 | 7.18KB |
HUGE | 200000 | 71.6MB |
You can generate a MEDIUM input file by issuing:
>rxgen 2000By default, the generated file is named rxgen.xml and is placed in Data subdirectory.
Note: There could be slight variation in size of the generated file everytime rxgen is run, even if the argument remains same.
XML File Size | Processing API | Parser Crimson: 1.1.1beta2 | Parser Xerces: 2.0.2beta2 | ||||
---|---|---|---|---|---|---|---|
1st Iteration (in milli secs.) |
Average (in milli secs.) |
Memory Usage (in KB) |
1st Iteration (in milli secs.) |
Average (in milli secs.) |
Memory Usage (in KB) |
||
TINY rxgen 20 9KB |
SAX | 50 | 24 | 101 | 50 | 24 | 37 |
DOM | 320 | 36 | 142 | 440 | 34 | 128 | |
PULL | 280 | 24 | 104 | 270 | 24 | 104 | |
JDOM | 270 | 47 | 162 | 280 | 44 | 135 | |
XSLT | 2030 | 147 | 463 | 2140 | 146 | 390 | |
COCOON | DIDN'T WORK WITH CRIMSON | 3790 | 248 | 848 | |||
SMALL rxgen 200 72KB |
SAX | 220 | 58 | 172 | 280 | 74 | 86 |
DOM | 550 | 91 | 385 | 610 | 121 | 446 | |
PULL | 500 | 80 | 746 | 490 | 80 | 746 | |
JDOM | 600 | 111 | 518 | 660 | 126 | 523 | |
XSLT | 2860 | 352 | 562 | 2910 | 328 | 905 | |
COCOON | DIDN'T WORK WITH CRIMSON | 4010 | 323 | 880 | |||
MEDIUM rxgen 2000 719KB |
SAX | 660 | 310 | 279 | 830 | 367 | 411 |
DOM | 1420 | 604 | 2897 | 1810 | 781 | 2842 | |
PULL | 1210 | 610 | 1244 | 1200 | 573 | 1819 | |
JDOM | 1930 | 860 | 3177 | 2030 | 945 | 2801 | |
XSLT | 5660 | 2477 | 2529 | 6040 | 2434 | 2535 | |
COCOON | DIDN'T WORK WITH CRIMSON | 5830 | 1254 | 900 | |||
BIG rxgen 20000 7197KB |
SAX | 3350 | 2946 | 352 | 4290 | 3570 | 450 |
DOM | 8350 | 5968 | 26.5MB | 10600 | 7030 | 25MB | |
PULL | 5880 | 5143 | 1496 | 5980 | 5270 | 1526 | |
JDOM | 18790 | 16013 | 26.9MB | 22740 | 17350 | 25MB | |
XSLT | 43400 | 38830 | 22780 | 43440 | 38170 | 21596 | |
COCOON | DIDN'T WORK WITH CRIMSON | 16750 | 10257 | 845 | |||
HUGE rxgen 200000 716MB |
SAX | 29330 | 28610 | 378 | 37290 | 36140 | 470 |
DOM | OUT OF MEMORY | OUT OF MEMORY | |||||
PULL | 52020 | 52840 | 1861 | 54320 | 51410 | 1841 | |
JDOM | OUT OF MEMORY | OUT OF MEMORY | |||||
XSLT | OUT OF MEMORY | OUT OF MEMORY | |||||
COCOON | DIDN'T WORK WITH CRIMSON | OUT OF MEMORY |
Careful analysis of the measurement figures under Mesurements and with few additional experimentation, a number of inferences can be made.
Note: The following conclusions are valid only for XStat processing under the specified Mesurement Environment. Care must be taken to apply these results to other situations.
Input Size | Processing Time | Memory Used | |||
---|---|---|---|---|---|
SAX | DOM | SAX | DOM | ||
TINY | 24ms | 36ms | 101KB | 142KB | |
SMALL | 58ms | 91ms | 172KB | 385KB | |
MEDIUM | 310ms | 604ms | 279KB | 2.90MB | |
BIG | 2.95s | 5.97s | 352KB | 26.5MB |
Interestingly, the method of measurement favours the DOM processing as the garbage collection is forced outside the measurement window. As DOM processing uses more memory objects, more time will be spent in garbage collection. So, in a real scenario, the DOM processing will have much worse performance than SAX.
Not surprisingly, the amount of memory used by SAX processing remains almost constant with input size whereas the memory used DOM processing increases in proportion to the input size. This could be a real problem for applications that are going to deal with large input or multiples of them simultaneously. DOM just won't scale.
The slight increase in memory for SAX processing with increase in input size is attributed to the memory objects holding the processing results and other bookkeeping info.
Input Size | Processing Time | Memory Used | |||
---|---|---|---|---|---|
Crimson | Xerces | Crimson | Xerces | ||
TINY | 24ms | 24ms | 101KB | 37KB | |
SMALL | 58ms | 74ms | 172KB | 86KB | |
MEDIUM | 310ms | 367ms | 279KB | 411KB | |
BIG | 2.95s | 3.57s | 352KB | 450KB | |
HUGE | 28.6s | 36.1s | 378KB | 470KB |
Note that the difference in processing speed is insignificant at small input size but is quite pronounced at very large input size. Another curious thing to note is that Xerces uses less memory for smaller inputs. Both these facts together could mean better performance with Xerces at moderate input size ( < 50 KB ).
Input Size | Processing Time | Memory Used | |||
---|---|---|---|---|---|
SAX | PULL | SAX | PULL | ||
TINY | 24ms | 24ms | 101KB | 104KB | |
SMALL | 58ms | 80ms | 172KB | 746KB | |
MEDIUM | 310ms | 610ms | 279KB | 1.24MB | |
BIG | 2.95s | 5.14s | 352KB | 1.50MB | |
HUGE | 28.6s | 52.84s | 378KB | 1.86MB |
This is hard to explain in theory as the Pull Parsing perhaps couldn't be more expensive. One practical explanation could be that the Pull Parser API is meant to be only peeking into first few elements and hence is not optimized for full document scan ( yet !).
Input Size | Processing Time | Memory Used | |||
---|---|---|---|---|---|
SAX | XSLT | SAX | XSLT | ||
TINY | 24ms | 147ms | 101KB | 463KB | |
SMALL | 58ms | 352ms | 172KB | 562KB | |
MEDIUM | 310ms | 2.47ms | 279KB | 2.53MB | |
BIG | 2.95s | 38.83s | 352KB | 22.7MB | |
HUGE | 28.6s | NA | 378KB | NA |
It appears that the transformer loads the whole document in memory. This certainly is not required for XStat processing..
Note: It might be possible to write XSL stylesheet in a way that avoids loading of whole document. If you know any such way, please do let me know.
Input Size | Processing Time | Memory Used | |||
---|---|---|---|---|---|
JDOM | DOM | JDOM | DOM | ||
TINY | 47ms | 36ms | 162KB | 142KB | |
SMALL | 111ms | 91ms | 518KB | 385KB | |
MEDIUM | 860ms | 604ms | 3.17KB | 2.90MB | |
BIG | 16.0s | 5.97s | 26.9MB | 26.5MB |
One might think that JDOM would be better at runtime and memory usage efficiency as it uses native Java classes. In reality, it compares poorly with DOM. But may be because JDOM software is still in beta and necessary optimizations haven't been carried out.
Input Size | Processing Time | Memory Used | |||
---|---|---|---|---|---|
xalan-2.1.0 | xalan-2.2.D10 | xalan2.1.0 | xalan-2.2.D10 | ||
MEDIUM | 8.57s | 2.48s | 4.7MB | 2.53MB | |
BIG | 756.0s | 38.0s | 46.6MB | 22.7MB |
The good news is that xalan performance is improving. However, as of now, you are better of avoiding XSL transformations in time critical situations.
------------------