Sunday, April 20, 2008

A comprehensive XML processing benchmark

by Eduardo Rodrigues


Introduction


I think I've already mentioned it here but, anyway, I'm currently leading a very interesting and challenging project for a big telecom company here in Brazil. This project is basically a complete reconstruction of the current data loading system used to process, validate and load all cellphone statements, which are stored as XML files, into an Oracle CMSDK 9.0.4.2.2 repository. For those who aren't familiar, Oracle CMSDK is an old content management product, which has succeeded the older Oracle iFS (Internet File System). Because it's not an open repository, we are obligated to use its Java API if we want to programmatically load or retrieve data into or from the repository. That, obviously, prevents us from taking advantage of some of the newest tools available like Oracle's XML DB or even the recent Oracle Data Integrator.

Motivation


One of our biggest concerns in this project is with the performance the new system must deliver. The SLA is really aggressive. So, we decided to make some research to find out the newest XML processing technologies available, try and compare them in order to make sure which ones would really help us in the most efficient way. The only constraints are: we must not consider any non-industry-standard solution nor any non-production (or non-stable) releases.

Test Sceneries


That said, based on research and also on previous experience, these were the technologies I've chosen to test and compare:

I've initially discarded DOM parsers based on the large average size of the XML files we'll be dealing with. We most certainly can't afford the excessive memory consumption involved. I've also discarded Oracle StAX Pull Parser, because it was still a preview release, and J2SE 5.0 built-in XML parsers, since I know they're a proprietary implementation of Apache Xerces based on a version certainly older than 2.9.1.

The test scenery designed was very simple and was intended only to measure and compare performance and memory consumption. The test job would be just to parse a real-world XML file containing 1 phone statement, retrieving and counting a predefined set of elements and attributes. In summary, rules were (for privacy's sake, real XML structure won't be revealed):
  1. Parse all occurrences of "/root/child1/StatementPage" element
  2. For each <StatementPage> do:
    1. Store and print out value of attribute "/root/child1/StatementPage/PageInfo/@pageNumber"
    2. Store and print out value of attribute "/root/child1/StatementPage/PageInfo/@customerCode"
    3. Store any occurrence of element <ValueRecord>, along with all its attributes, within page's subtree
    4. Print out the number of <ValueRecord> elements stored
  3. Print out the total number of <StatementPage> elements parsed
  4. Print out the total number of <ValueRecord> elements parsed

Also, every test should be performed for 2 different XML files: a small file (6.5MB), containing a total of 420 statement pages and 19,133 value records and a large one (143MB) with 7,104 pages and 464,357 value records.

Based on the rules above, I then tested and compared the following technology sets:
  1. Apache Digester using Apache Xerces2 SAX2 parser
  2. Apache Digester using Oracle SAX2 parser
  3. Sun JAXB2 using Xerces2 SAX2 parser
  4. Sun JAXB2 using Oracle SAX2 parser
  5. Sun JAXB2 using Woodstox StAX1 parser
  6. Pure Xerces2 SAX2 parser
  7. Pure Oracle SAX2 parser
  8. Pure Woodstox StAX1 parser

Based on this tutorial fragment from Sun: http://java.sun.com/webservices/docs/1.6/tutorial/doc/SJSXP3.html and considering that performance is our primary goal, I've chosen StAX's cursor API (XMLStreamReader) over iterator. Still aiming for performance, all tested parsers have been configured as non-validating.

In time; all tests were executed on a Dell Latitude D620 notebook, with an Intel Centrino DUO T2400 CPU @ 1.83GHz running on Windows XP Professional SP2 and Sun's Java VM 1.5.0_15 in client mode.

Results


These were the performance results obtained after parsing the small XML file (for obvious reasons, I decided to measure heap usage only when the large file was parsed):

Performance results for small XML file
As you can see, Apache Digester's performance was extremely and surprisingly poor despite all my efforts to improve it. So, I had no other choice than to discard it for next tests with the large XML file, from which the results are presented bellow:

Performance results for large XML file
Notice that the tendency toward a better performance when <!DOCTYPE> tag is removed from the XML document has been clearly confirmed here.

As for memory allocation comparison, I've once again narrowed the tests only to the worst case from performance tests above: large XML file including <!DOCTYPE> tag. The results obtained from JDev's memory profiler were:

Memory allocation for large XML file
Another interesting information we can extract from these tests is how much XML binding represents in terms of overhead when compared to a straight parser:

Overhead charts

Conclusion


After a careful and thorough revision and confirmation of all results obtained from the tests described here, I tend to recommend a mixed solution. Considering its near 12MB/s throughput verified here, I'd certainly choose pure Woodstox StAX parser every time I'll have to deal with medium to large XML sources but, for convenience, I'd also choose JAXB 2 whenever there's a XML schema available to compile its classes from and the size of the source XML is not a concern.

As for complexity, I really can't say that any one of the tested technologies was found considerably more complex to implement than the others. In fact, I don't think this would be an issue for anybody with an average experience with XML processing.

Important Note


Just for curiosity, I've also tested Codehaus StaxMate 1.1 along with Woodstox StAX parser. It's a helper library built on top of StAX in order to create an easier to use abstraction layer for StAX cursor API. I can confirm the implementor's affirmation that StaxMate shouldn't represent any significant overhead for performance. In fact, performance results were identical when compared to pure Woodstox StAX parsing the large XML file. I can also say that it really made my job pretty easier. The only reason I won't consider StaxMate is that it depends on a StAX 1.0 API non-standard extension which is being called "StAX2" by guys at Codehaus.

That's all for now.

Enjoy and... keep reading!

Saturday, April 19, 2008

Fixed blog's appearance on IE6

Great news folks!

We've just fixed our blog's template so it'll be displayed 100% correctly on Internet Explorer 6 browser. Now, we expect this blog to render identically on both Internet Explorer and Firefox (hopefully on all other browsers too).

Please, let us know if there's still any visualization issues.

Cheers and... keep reading!

Wednesday, April 16, 2008

Is there a cook in JDev's team?

This week I found something at least very curious when I launched my JDeveloper 10.1.3.3 as I do almost every morning. This was the "Tip of the Day" it showed me:



Well, I don't know what this means but, anyway, here is a full recipe, just in case: http://www.foodnetwork.com/food/recipes/recipe/0,1977,FOOD_9936_15602,00.html

:)

Monday, March 31, 2008

Using FindBugs in JDeveloper 10g

by Fábio Souza

FindBugs Logo
These days I've been looking for a good way to incorporate FindBugsTM within my JDeveloper 10g and I couldn't find anything about it on the net. I talked with Eduardo and we both thought it would be a good idea to configure FindBugs as a JDeveloper External Tool (and it is indeed).

Ok, before I start listing the steps to do it, I must say I'm pretty much aware of the fact that you will probably notice that I'm using Eduardo's JAXB 2.0 configuration steps listed on his previous post "JAXB 1.0 vs. 2.0 in JDeveloper 10g". Well... what can I say? I am a CTRL+C/CTRL+V addicted and I just can't help it! :D
  1. Click the menu item "Tools -> External Tools..."

  2. Press the "New..." button to start the "Create External Tool" wizard

  3. Select "External Program" as the "Tool Type" and press "Next"

  4. Fill the 3 displayed fields as follows:

    1. Program Executable:

      full path to the "java.exe" from your preferred JAVA_HOME (must be Java 5.0 or greater)

    2. Arguments:

      -Dfindbugs.home=. -Xmx256m -jar lib\findbugs.jar -sourcepath "${project.first.sourcepath}" -auxclasspath "${project.classpath}" -html -output "${project.dir}\${file.name.no.ext}.findbugs.html" "${project.outputdirectory}" "${project.outputdirectory}"

      The arguments above will be passed to "java.exe". Notice that we're bypassing "findbugs.bat" and executing the FindBugs JAR file directly. We must do this way because the batch file requires the classpath passed after "-auxclasspath" to be enclosed in double quotes (") and the macro "${project.classpath}" will match that requirement only when there's at least one path including one ore more blank spaces in its directories names.

    3. Run Directory:

      full path where FindBugs is installed.

  5. Press "Next" to advance to "Display" step and fill the 3 fields as you like. I suggest the following:

    1. Caption for Menu Items:

      FindBugs

    2. ToolTip Text:

      Run FindBugs on your project.

    3. Icon location:

      Download and configure this one -> FingBugs icon

    4. Press "Next" to advance to "Integration" step where I recommend selecting "Tools Menu" and "Navigator Context Menu"

    5. Press "Next" to advance to the final step "Availability". Here, you have to choose the option "When Specific File Types are Selected" and then move only the item "Java Project" from list "Available Types" to list "Selected Types"

    6. Press "Finish" and done!

Attention! I got an error while trying to use FindBugs in my JDeveloper 10.1.3.3. When "${project.classpath}" is expanded after "-auxclasspath", it includes the Java library paths as well. But, I don't know why, the default JDeveloper's Java SE library has i18n.jar, sunrasign.jar and the "classes" folder included in its classpath but these three items actually don't exist, so FindBugs will abort when it tries to locate them. I had to remove these items from my JDeveloper Java SE Library classpath to solve this problem.

Now it's all set to use FindBugs! Just right-click on a project in the Application Navigator and select "FindBugs". An HTML report will be generated in project's folder and standard output and error will be sent to JDev's Message View.

Enjoy your new tool!

Thursday, March 13, 2008

Important Tip for Clustered OracleAS 10.1.3.3.0

by Eduardo Rodrigues

Hi everybody!

Recently we've upgraded OracleAS environments in one of our biggest clients here in Brazil from version 10.1.3.0.0 to version 10.1.3.3.0. To do that, we've applied patchset #6148874 (which can be downloaded from Oracle Metalink) carefully following all the instructions found in its installation guide. As expected, the patchset application went perfectly fine and all of our configured containers and applications were still there, up and running, and everybody was happy... until we noticed that one of our oldest and most annoying problems was still there: using ASControl to manage our clustered production environment sometimes was just impossible due to its unacceptable performance when trying to access anything in cluster topology context.

Unfortunately, the only workaround we knew was to restart ASControl application in the cluster's "master node" (the node elected to run the ascontrol application). Fortunately, today I found the problem and also the solution for this situation.

There's a documented bug on Metalink (bug #6601697) explaining that this problem is caused by the underlying RMI communication between the ASControl 10.1.3.3.0 and the other components of the cluster. ASControl uses RMI protocol to connect to other nodes, makes some request and then waits for a response. The problem is that there's no timeout for this response waiting. If one or more components are in a heavy load situation, for example, ASControl will keep waiting for their responses, which can take too long, causing the impression that ASControl stopped working.

In fact, this problem is known since version 10.1.3.1.0 but it seems that patchset 10.1.3.3.0 does not include the correction as it should. So, for now, the solution is to apply the one-off patch #6124143, also found on Metalink. This patch is originally targeted to OracleAS 10.1.3.1.0 but, as written in bug #6601697, it's ok to apply it on version 10.1.3.3.0 though. We just have to follow these simple instructions, found in the bug, before actually applying it:
  1. Edit the patch file etc/config/actions and replace 10.1.3.1.0 by 10.1.3.3.0

  2. Edit etc/config/inventory and replace 10.1.3.1.0 by 10.1.3.3.0

Once it's successfully applied, we must use ASControl to navigate to the OC4J instance where ascontrol application is running (typically the "home" instance). Click on Administration -> Server Properties -> Command Line Options -> Start-parameters: Java Options and add "-Drmi.client.connection.timeout=X", where "X" should be the number of seconds to wait for a RMI response before timeout. The bug suggests 5 seconds.

We've successfully applied this one-off patch in our OracleAS 10.1.3.3.0 environment and, until now, it seems to have solved the problem.

I feel this might be a problem faced by many other OracleAS 10.1.3 users so I hope this post can help them.

Cheers and... keep reading!