Skip to Content.
Sympa Menu

xom-interest - [XOM-interest] Some minor issues

xom-interest AT lists.ibiblio.org

Subject: XOM API for Processing XML with Java

List archive

Chronological Thread  
  • From: Wolfgang Hoschek <whoschek AT lbl.gov>
  • To: xom-interest AT lists.ibiblio.org
  • Subject: [XOM-interest] Some minor issues
  • Date: Fri, 3 Dec 2004 12:47:07 -0800

I'd like to bring up a few minor issues for clarification.

1) Element copy constructor

In my use cases it is extremely common to use new Element(Element), copying an element with no children, no attributes and no namespaces, later adding children separately. This improves performance (avoids reverification and indexOf) and saves memory (avoids new String creations), leading to a form of string interning that helps performance elsewhere. But Element.nonrecursiveCopy() is quite inefficient for that case, even though there's really nothing to do for it, since there are no children. The fix is to have:

public Element(Element elem) {
...
this.actualBaseURI = element.findActualBaseURI();
if (getChildCount() > 0) // WH patch; avoid work if there's nothing to do anyway
nonrecursiveCopy(element, this);

[You could also move the getChildCount() > 0 check into nonrecursiveCopy() if desired]

2) Moving attributes into Element (see a prior thread)

I don't quite see how this could possibly increase memory consumption. Rather it reduces it slightly by eliminating one pointer to store. A pointer takes 4 bytes, and all pointers are the same, so where would there be a difference? Perhaps you accidentally initialized the ArrayList to something other than "null", which it normally is. Please check your measurements (or tools or methodology - memory consumption is notoriously hard to measure). The change also improves performance, as discussed earlier.

3) Verifier.checkPCDATA

FYI, there are still Unicode calculations (multiplications, etc) in decodeSurrogatePair that are entirely unnecessary. Actually the entire method is unnecessary. My fastest version is as follows (retaining semantics unchanged):

static void checkPCDATA(String text) {
if (!checkPCDATA) return;
if (text == null)
throwIllegalCharacterDataException(text, "Null text");
// char[] data = text.toCharArray();
byte[] myFlags = flags; // cache static var
// try {
for (int i = 0, len = text.length(); i < len; i++) {
int result = text.charAt(i);
if (result >= 0xD800 && result <= 0xDBFF) {
i++; // increment past low surrogate
int low = (i < len ? text.charAt(i) :
0);
if (low < 0xDC00 || low > 0xDFFF) {

throwIllegalCharacterDataException(text,
"Bad surrogate
pair");
}
// result =
decodeSurrogatePair(result, data[i+1]);
// all properly matched surrogate
pairs are legal in PCDATA
} // end if
else {
try {
if ((myFlags[result] &
XML_CHARACTER) == 0) {

throwIllegalCharacterDataException(text, "0x"
+
Integer.toHexString(result)
+ " is not
allowed in XML content");
}
} catch
(ArrayIndexOutOfBoundsException ex) {

throwIllegalCharacterDataException(text, "Bad Surrogate Pair");
// IllegalCharacterDataException ide = new IllegalCharacterDataException(
// "Bad Surrogate
Pair", ex);
// ide.setData(text);
// throw ide;
}
}
}
// not needed anymore
// catch (IllegalCharacterDataException ex) {
// ex.setData(text);
// throw ex;
// }

}


4) Verifier.URICache

Lock contention issues matter, IMHO. Any news on where the weird non-interned URIs you mentioned come from? Are they from different calls to Builder.build()? Perhaps xerces uses a new pool for each build, which should not be a real issue. If there are comparatively few cache misse that's not really a performance problem. What matters is the overall cache hit/miss ratio. If you measured the hit ratio, please let me know.

5) If you could remove the URICache String.equals() calls, apply the PCDATA and Element patches above i could get rid of maintaining lots of quite unnecessary patches, which would be a relief :-)

Thanks,
Wolfgang.





Archive powered by MHonArc 2.6.24.

Top of Page