Hi all,
Over at the Apache Batik project we recently switched from Crimson
to Xerces. At that time we noticed that Xerces has a severe
performance issue with large attributes (it appears at least in
versions 2.3 and 2.4).
In SVG large attributes are very common as the path data is stored in
'd' attributes (often several Kilobytes in size) and even worse SVG
requires support for the 'data' protocol and base64 encoding of image
and other file types in xlink:href attributes (where hundreds of kilobytes
or even megabytes may be encountered).
I've attached a patch that makes XMLStringBuffer use array doubling
instead of a fixed 32 char increment. For one of our test files with
a 500Kb embedded image, this patch reduces parse time from ~4.5min to
.8 sec (n*log(n) is much better than n^2). This is not even a
particularly extreme case for SVG.
You might consider pulling the buffer reallocation code out into
an 'ensureCapacity(int len)' method, but I didn't want to add a new
method to your existing interface.
? XMLStringBufferAlloc.patch
? build
Index: src/org/apache/xerces/util/XMLStringBuffer.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/util/XMLStringBuffer.java,v
retrieving revision 1.4
diff -w -u -r1.4 XMLStringBuffer.java
--- src/org/apache/xerces/util/XMLStringBuffer.java 29 Jan 2002 01:15:18 -0000
1.4
+++ src/org/apache/xerces/util/XMLStringBuffer.java 26 Jul 2003 12:56:26 -0000
@@ -91,15 +91,6 @@
public static final int DEFAULT_SIZE = 32;
//
- // Data
- //
-
- // private
-
- /** One char buffer. */
- private char[] fOneCharBuffer = new char[1];
-
- //
// Constructors
//
@@ -159,8 +150,16 @@
* @param c
*/
public void append(char c) {
- fOneCharBuffer[0] = c;
- append(fOneCharBuffer, 0, 1);
+ if (this.length + 1 > this.ch.length) {
+ int newLength = this.ch.length*2;
+ if (newLength < this.ch.length + DEFAULT_SIZE)
+ newLength = this.ch.length + DEFAULT_SIZE;
+ char[] newch = new char[newLength];
+ System.arraycopy(this.ch, 0, newch, 0, this.length);
+ this.ch = newch;
+ }
+ this.ch[this.length] = c;
+ this.length++;
} // append(char)
/**
@@ -171,7 +170,10 @@
public void append(String s) {
int length = s.length();
if (this.length + length > this.ch.length) {
- char[] newch = new char[this.ch.length + length + DEFAULT_SIZE];
+ int newLength = this.ch.length*2;
+ if (newLength < this.length + length + DEFAULT_SIZE)
+ newLength = this.ch.length + length + DEFAULT_SIZE;
+ char[] newch = new char[newLength];
System.arraycopy(this.ch, 0, newch, 0, this.length);
this.ch = newch;
}
@@ -188,7 +190,10 @@
*/
public void append(char[] ch, int offset, int length) {
if (this.length + length > this.ch.length) {
- char[] newch = new char[this.ch.length + length + DEFAULT_SIZE];
+ int newLength = this.ch.length*2;
+ if (newLength < this.length + length + DEFAULT_SIZE)
+ newLength = this.ch.length + length + DEFAULT_SIZE;
+ char[] newch = new char[newLength];
System.arraycopy(this.ch, 0, newch, 0, this.length);
this.ch = newch;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]