[jdom-interest] Performance tests

philip.nelson at omniresources.com philip.nelson at omniresources.com
Wed May 9 08:45:57 PDT 2001

> I used Xerces in the tests, but tried Crimson as well and 
> didn't see much difference.
> The simple SAX parse time is less than 1/3 of the JDOM 
> document build time, and all
> the tests except Electric XML use the same parser, so 
> changing the parser is not
> going to dramatically change the results.

I am having trouble reproducing your results.  I used a variant of the
Compare class that somebody sent in.  I added a little code to prime the
builder by doing a sax parse of a simple in memory document for both DOM and
JDOM (using SAXBuilder assuming that DOM would have to load the same
classes).  I worked with a small, 8K document with lots of attributes and no
namespaces in order to have a manageable trace file.  I did find a
performance enhancement for Element.setAttribute that saved me about 8% but
basically, the majority of time is spent outside of the JDOM classes.  We
can save another 6-9% if we had a way to turn off the Verifier which is not
needed when building but would be difficult to turn off.  With my
enhancement, JDOM was faster than the default Xerces DOM build (deferred
building) by a small margin.  I did not force Xerces to walk the tree. 

I have included the patch for Element which should go in any case.
removeAttribute is called *every time* setAttribute is called, whether it
needs to be or not.  This means iterating through the entire list multiple
times for every call.  My patch eliminates this for the most normal case of
building a new document from xml source.

I have also included a screen shot of the JInsight visualization of the
trace.  SAXBuilder.Build is a slice of the trace from the start of the
build. The 100% time means the total time spent in that routine, not the
total time for the full test.  SAXScanElement.gif shows that the majority of
the time is not spent doing JDOM specific things.  It would appear that
there is still room for optimization, but we're in the <20% range, at least
for this document.  Most of the time is consumed by the parser itself.  I
will test next with a document with namespaces and one with lots of element

    public Element setAttribute(Attribute attribute) {
        if (attribute.getParent() != null) {
            throw new IllegalAddException(this, attribute,
                "The attribute already has an existing parent \"" +
                attribute.getParent().getQualifiedName() + "\"");
		//flag to help determine if we need to remove an old version
        boolean preExisting = false;
        // Verify the attribute's namespace prefix doesn't collide with
        // another attribute prefix or this element's prefix.
        // This is unfortunately pretty heavyweight but we don't need to do
        // for attributes without a namespace, and a little testing shows no
        // real difference in build times anyway.
        String prefix = attribute.getNamespace().getPrefix();
        if (!prefix.equals("")) {
          String uri = attribute.getNamespace().getURI();
          if (prefix.equals(getNamespacePrefix()) && 
                !uri.equals(getNamespaceURI())) {
              throw new IllegalAddException(this, attribute,
                "The attribute namespace prefix \"" + prefix + 
                "\" collides with the element namespace prefix");
          if (additionalNamespaces != null && additionalNamespaces.size() >
0) {
              Iterator itr = additionalNamespaces.iterator();
              while (itr.hasNext()) {
                  Namespace ns = (Namespace) itr.next();
                  if (prefix.equals(ns.getPrefix()) && 
                        !uri.equals(ns.getURI())) {
                      throw new IllegalAddException(this, attribute,
                        "The attribute namespace prefix \"" + prefix +
                        "\" collides with a namespace declared by the
          if (attributes != null && attributes.size() > 0) {
              Iterator itr = attributes.iterator();
              while (itr.hasNext()) {
	              Attribute att = (Attribute)itr.next();
                  Namespace ns = att.getNamespace();
                  //keep track if we have and existing attribute
                  if (attribute.getName().equals(att.getName()) &&
	                  	preExisting = true;
                  if (prefix.equals(ns.getPrefix()) && 
                        !uri.equals(ns.getURI())) {
                      throw new IllegalAddException(this, attribute,
                          "The attribute namespace prefix \"" + prefix +
                          "\" collides with another attribute namespace on "
                          "the element");
        if (attributes == null) {
            attributes = new LinkedList();
        else if (preExisting) {
            // Remove any pre-existing attribute
            removeAttribute(attribute.getName(), attribute.getNamespace());

        return this;

-------------- next part --------------
A non-text attachment was scrubbed...
Name: SAXScanElement.gif
Type: image/gif
Size: 20885 bytes
Desc: not available
Url : http://jdom.org/pipermail/jdom-interest/attachments/20010509/890982c8/SAXScanElement.gif
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SAXBuilderBuild.gif
Type: image/gif
Size: 25733 bytes
Desc: not available
Url : http://jdom.org/pipermail/jdom-interest/attachments/20010509/890982c8/SAXBuilderBuild.gif
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Compare.java
Type: application/octet-stream
Size: 3174 bytes
Desc: not available
Url : http://jdom.org/pipermail/jdom-interest/attachments/20010509/890982c8/Compare.obj

More information about the jdom-interest mailing list