我试图使用javax.xml.xpath包在具有多个命名空间的文档上运行XPath表达式,并且我有愚蠢的性能问题。
我的测试文件是从一个真实的生产实例中抽出来的。大约600k xml。该文档是一个相当复杂的Atom提要。
我知道我在做XPath可以做到没有。然而,在其他较差的平台上,同样的实施方式表现得更为荒谬。现在,重建我的系统不使用XPath超出了我能做的时间范围。
我的测试代码是这样的:
void testXPathPerformance()
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(loadTestDocument());
XPathFactory xpf = XPathFactory.newInstance();
XPath xp = xpf.newXPath();
NamespaceContext names = loadTestNamespaces();
//there are 12 namespaces in names. In this example code, I'm using
//'samplens' instead of the actual namespaces that my application uses
//for simplicity. In my real code, the queries are different text, but
//precisely the same complexity.
xp.setNamespaceContext(names);
NodeList nodes = (NodeList) xp.evaluate("/atom:feed/atom:entry",
doc.getDocumentElement(), XPathConstants.NODESET);
for(int i=0;i
{
printTimestamp(1);
xp.evaluate("atom:id/text()", nodes.item(i));
printTimestamp(2);
xp.evaluate("samplens:fieldA/text()", nodes.item(i));
printTimestamp(3);
xp.evaluate("atom:author/atom:uri/text()", nodes.item(i));
printTimestamp(4);
xp.evaluate("samplens:fieldA/samplens:fieldB/&at;attrC", nodes.item(i));
printTimestamp(5);
//etc. My real example has 10 of these xp.evaluate lines
}
}
当我运行Nexus One时,(不是在调试器中,而是连接USB),首次通过循环,每个xp.evaluate需要10ms到20ms的地方。在第15次循环之前,每个xp.evaluate需要从200ms到300ms。在循环结束(节点中有150个项目),每个xp.evaluate需要大约500ms-600ms。
我试过使用xp.compile()。编译器都采取< 5ms。我已经完成了xp.reset()(没有区别)。我为每个评估完成了一个新的XPath对象(增加了大约4ms)。 在执行过程中,内存使用情况似乎不会失去控制。 我在JUnit测试用例中的单个线程上运行此操作,但不会创建活动或任何内容。 我真的很困惑 有人有什么想法还有什么尝试吗? 谢谢! 更新 如果我向后运行for循环(for(int i = nodes.getLength() – 1; i> = 0; i–)),那么前几个节点需要500ms-600ms,最后一个节点快速运行10ms -20ms。所以,这似乎与调用次数无关,而是上下文靠近文档末尾的表达式比上下文靠近文档开头的表达式要长。
有人有什么想法可以做到这一点吗?