XPath evaluate() calls becoming slower and slower...
843834Feb 18 2005 — edited Feb 18 2005Greetings,
I'm having a wierd problem in my java application with XPath queries (using Sun's
default XPath API in 1.5.0).
The problem is that XPath.evaluate() is slower everytime I call it.
(What used to take 5 to 10 seconds to parse using DOM calls now takes up to 2 minutes using XPath!)
For example:
I have a XML document (given by Ganglia, around 300K in size), which
contains many "HOST" nodes, each of them containing many "METRIC" nodes.
Something like:
<GANGLIA_XML>
<HOST>
<METRIC NAME="..." .../>
<METRIC NAME="..." .../>
<METRIC NAME="..." .../>
<METRIC NAME="..." .../>
...
</HOST>
<HOST>
<METRIC NAME="..." .../>
<METRIC NAME="..." .../>
<METRIC NAME="..." .../>
<METRIC NAME="..." .../>
...
</HOST>
...
</GANGLIA_XML>
Now if I get a NodeList of HOST nodes (using XPath.evaluate), and then for
each of these node get a NodeList of "METRIC" nodes (again using
XPath.evaluate), then when I iterate through the METRIC node list and
evaluate each of them to get the "NAME" attribute value (using
xpath.evaluate("@NAME", doc, ...), the performance of each XPath query to
do so gets slower and slower for each successive XPath.evaluate call.
Did anyone experience this behavior before? Any idea why this is happening?
Here is a snapshot of a little test application that reproduces this
behavior: (in this test app I simply get all the METRIC nodes right away,
but the performance problem still happens)
---------------------------------
public class Test
{
public static void main(String[] args)
{
try
{
DocumentBuilder db =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = db.parse(new File("ganglia.output.xml));
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList metricNodes = (NodeList) xpath.evaluate("//METRIC", doc,
XPathConstants.NODESET);
for(int i = 0; i < metricNodes.getLength(); i++)
{
Node n = metricNodes.item(i);
long t1 = Calendar.getInstance().getTimeInMillis();
String s = (String) xpath.evaluate("@NAME", n, XPathConstants.STRING);
long t2 = Calendar.getInstance().getTimeInMillis();
System.out.println("time: " + (t2 - t1));
}
}
catch(Exception e)
{
System.out.println("Error: " + e);
}
System.exit(0);
}
}
---------------------------------
Thanks,
Andre