java xpath evaluate_java – XPath.evaluate性能在多个调用中减慢(荒谬)

我试图使用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。所以,这似乎与调用次数无关,而是上下文靠近文档末尾的表达式比上下文靠近文档开头的表达式要长。

有人有什么想法可以做到这一点吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生成XPath: 如果你有一个XML节点,可以使用getNodePath()方法来获取该节点的XPath。 例如,假设你有一个org.w3c.dom.Node对象,通过调用getNodePath()方法,你可以获取该节点的XPathNode node = ...; String xpath = ((org.apache.xpath.Node) node).getNodePath(); 获取XPath: 如果你已经知道了要获取的节点的XPath,可以使用javax.xml.xpathXPath API来获取该节点。 例如,假设你有以下XML文档: <?xml version="1.0" encoding="UTF-8"?> <root> <element1>value1</element1> <element2> <subelement1>value2</subelement1> <subelement2>value3</subelement2> </element2> </root> 要获取根节点的XPath,你可以使用如下代码: DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(new File("path/to/xml/file.xml")); XPathFactory xPathfactory = XPathFactory.newInstance(); XPath xpath = xPathfactory.newXPath(); String rootNodeXPath = "/"; Node rootNode = (Node) xpath.evaluate(rootNodeXPath, doc, XPathConstants.NODE); 要获取子节点element1的XPath,你可以使用如下代码: String element1XPath = "/root/element1"; Node element1 = (Node) xpath.evaluate(element1XPath, doc, XPathConstants.NODE); 要获取子节点element2下的子节点subelement1的XPath,你可以使用如下代码: String subelement1XPath = "/root/element2/subelement1"; Node subelement1 = (Node) xpath.evaluate(subelement1XPath, doc, XPathConstants.NODE);

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值