首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >XOM规范化花费的时间太长

XOM规范化花费的时间太长
EN

Stack Overflow用户
提问于 2012-11-25 23:44:08
回答 3查看 481关注 0票数 2

我有一个可以大到1 1GB的XML文件。我使用XOM来避免OutOfMemory异常。

我需要规范化整个文档,但规范化需要很长时间,即使对于1.5MB的文件也是如此。

以下是我所做的工作:

我有这个示例XML文件,并通过复制Item节点增加了文档的大小。

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Packet id="some" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Head>
<PacketId>a34567890</PacketId>
<PacketHeadItem1>12345</PacketHeadItem1>
<PacketHeadItem2>1</PacketHeadItem2>
<PacketHeadItem3>18</PacketHeadItem3>
<PacketHeadItem4/>
<PacketHeadItem5>12082011111408</PacketHeadItem5>
<PacketHeadItem6>1</PacketHeadItem6>
</Head>
<List id="list">
    <Item>
        <Item1>item1</Item1>
        <Item2>item2</Item2>
        <Item3>item3</Item3>
        <Item4>item4</Item4>
        <Item5>item5</Item5>
        <Item6>item6</Item6>
        <Item7>item7</Item7>
    </Item>
</List>
</Packet>

我用于规范化的代码如下:

代码语言:javascript
运行
复制
private static void canonXOM() throws Exception {
    String file = "D:\\PACKET.xml";
    FileInputStream xmlFile = new FileInputStream(file);

    Builder builder = new Builder(false);
    Document doc = builder.build(xmlFile);

    FileOutputStream fos = new FileOutputStream("D:\\canon.xml");
    Canonicalizer outputter = new Canonicalizer(fos);

    System.out.println("Query");
    Nodes nodes = doc.getRootElement().query("./descendant-or-self::node()|./@*");

    System.out.println("Canon");
    outputter.write(nodes);

    fos.close();
}

尽管这段代码可以很好地处理小文件,但在我的开发环境(4 4gb ram、64位、eclipse、windows)上,1.5mb文件的规范化部分需要大约7分钟。

任何指向此延迟原因的提示都将不胜感激。

PS。我需要规范化来自整个XML文档以及整个文档本身的片段。因此,使用文档本身作为参数对我来说不起作用。

最好的

EN

回答 3

Stack Overflow用户

发布于 2012-12-05 18:37:49

代码语言:javascript
运行
复制
memory is not restriction

代码语言:javascript
运行
复制
main thread is green and no blocking. it is using as much cpu as it can. 
because my machine has multi-cores , so the CPU total usage is not full.
But it will be full for a single CPU the main thread is running on.

代码语言:javascript
运行
复制
Nodes.contains is the most busy one

内部节点以列表的形式进行管理,并进行线性比较。列表中的项目越多,“包含”的速度就会变慢。

代码语言:javascript
运行
复制
private final List nodes;
public boolean contains(Node node) {
    return nodes.contains(node);
}

所以

  • 尝试将库的代码修改为使用HashMap来保存节点。
  • 或使用多线程来利用更多的CPU(如果您的
  • 可以拆分成较小的XML )。

工具: JVisualVM。http://docs.oracle.com/javase/6/docs/technotes/guides/visualvm/index.html

票数 1
EN

Stack Overflow用户

发布于 2012-12-05 21:58:34

既然你想序列化整个文档,你能不能直接替换

代码语言:javascript
运行
复制
Nodes nodes = doc.getRootElement().query("./descendant-or-self::node()|./@*");
outputter.write(nodes);

使用

代码语言:javascript
运行
复制
outputter.write(doc);

当给出一个节点列表而不仅仅是一个要规范化的根节点时,看起来Canonicalizer做了额外的工作(比如whunmr提到的nodes.contains()调用)。

如果这不起作用或者还不够,我会派生Canonicalizer并按照性能分析的建议在那里进行优化。

票数 0
EN

Stack Overflow用户

发布于 2012-12-06 22:12:11

如果您愿意放弃XOM,我可能有一个解决您问题的方法。我的解决方案包括使用XPath APIApache Santuario

性能上的差异是令人印象深刻的,但我认为提供一个比较会很好。

对于测试,我使用了您在问题中提供的1.5MB的XML文件。

XOM测试

代码语言:javascript
运行
复制
FileInputStream xmlFile = new FileInputStream("input.xml");

Builder builder = new Builder(false);
Document doc = builder.build(xmlFile);

FileOutputStream fos = new FileOutputStream("output.xml");
nu.xom.canonical.Canonicalizer outputter = new nu.xom.canonical.Canonicalizer(fos);

Nodes nodes = doc.getRootElement().query("./descendant-or-self::node()|./@*");
outputter.write(nodes);

fos.close();

XPath/Santuario测试

代码语言:javascript
运行
复制
org.apache.xml.security.Init.init();

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
org.w3c.dom.Document doc = builder.parse("input.xml");

XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpath = xpathFactory.newXPath();

org.w3c.dom.NodeList result = (org.w3c.dom.NodeList) xpath.evaluate("./descendant-or-self::node()|./@*", doc, XPathConstants.NODESET);

Canonicalizer canon = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS);
byte canonXmlBytes[] = canon.canonicalizeXPathNodeSet(result);

IOUtils.write(canonXmlBytes, new FileOutputStream(new File("output.xml")));

结果

下面是以秒为单位的结果表。测试进行了16次。

代码语言:javascript
运行
复制
╔═════════════════╦═════════╦═══════════╗
║      Test       ║ Average ║ Std. Dev. ║
╠═════════════════╬═════════╬═══════════╣
║ XOM             ║ 140.433 ║   4.851   ║
╠═════════════════╬═════════╬═══════════╣
║ XPath/Santuario ║ 2.4585  ║  0.11187  ║
╚═════════════════╩═════════╩═══════════╝

性能上的差异是巨大的,这与XML Path Language的实现有关。使用XPath/Santuario的缺点是它们不像XOM那么简单。

测试详细信息

计算机:英特尔酷睿i5 4 4GB内存

所以: Debian 6.0 64位

Java: OpenJDK 1.6.0_18 64位

XOM: 1.2.8

Apache Santuario: 1.5.3

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13552555

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档