为啥 sax 解析比 dom 解析快?以及 stax 是如何工作的?
Posted
技术标签:
【中文标题】为啥 sax 解析比 dom 解析快?以及 stax 是如何工作的?【英文标题】:why is sax parsing faster than dom parsing ? and how does stax work?为什么 sax 解析比 dom 解析快?以及 stax 是如何工作的? 【发布时间】:2011-04-19 00:29:18 【问题描述】:有点相关:libxml2 from java
是的,这个问题相当冗长 - 抱歉。我保持尽可能密集。我将问题加粗,以便在阅读整篇文章之前更容易查看。
为什么 sax 解析比 dom 解析更快? 我唯一能想到的是,使用 sax 您可能会忽略大部分传入数据,因此不会浪费时间处理您不关心的 xml 部分。 IOW - 使用 SAX 解析后,您无法重新创建原始输入。 如果您编写 SAX 解析器以便它解释每个 xml 节点(并因此可以重新创建原始节点),那么它不会比 DOM 快吗?
我问的原因是我试图更快地解析 xml 文档。我需要在解析后访问整个 xml 树。我正在为要插入的 3rd 方服务编写一个平台,所以我无法预测需要 xml 文档的哪些部分,哪些部分不需要。我什至不知道传入文档的结构。这就是我不能使用 jaxb 或 sax 的原因。内存占用对我来说不是问题,因为 xml 文档很小,我一次只需要 1 个内存。解析这个相对较小的 xml 文档需要花费时间,这让我很头疼。我以前没有使用过 stax ,但也许我需要进一步调查,因为它可能是中间立场? 如果我理解正确的话,stax会保持原来的xml结构,并按需处理我要求的部分?这样,原来的解析时间可能很快,但每次我要求它遍历部分还没有遍历的树,那是处理发生的时候?
如果您提供的链接回答了大部分问题,我会接受您的回答(如果我的问题已经在其他地方得到回答,您不必直接回答)。
更新:我用 sax 重写了它,它解析文档的时间平均为 2.1 毫秒。与 dom 所花费的 2.5 毫秒相比,这是一个改进(快了 16%),但这并不是我(等人)猜到的幅度
谢谢
【问题讨论】:
我想说哪个更快的问题与您的目的无关,因为您需要对树进行任意查询。这意味着您必须构建树的一些表示,并有一些方法来创建针对它的查询。因此,要么使用 DOM/XPath,要么编写自己的等价物。 但是,我怀疑您真正的问题不是 SAX 与 DOM 本身,而是您的系统如何配置和/或您如何访问数据。使用 DOM(或 DOM 等效项之一)解析“小”文档确实不需要那么长时间。您是否量化了 SAX 和 DOM 之间的差异(您所看到的)? 我已经量化了 DOM 方法。小(大约 300k)xml 文档。当前的实现使用 xerces-j,在 1.5 GHz 机器上每个 xml 文档大约需要 2.5 ms。量化 sax 在某种程度上取决于您选择保留多少 xml 以及您用它做什么。你是对的——我认为萨克斯对我不起作用——这个问题更多是出于好奇。 2.5 毫秒似乎真的没那么糟糕。如果您只是想满足好奇心,我建议您使用以下比较程序:(1)使用进行 UTF-8 转换的 InputStreamReader 读取文件,以及(2)使用空 @ 通过 SAX 解析文档987654322@(即,让它解析和调度,但不对结果做任何事情)。 也就是说,如果您通过 DOM 推送大量文档,垃圾收集可能会成为一个问题:它们往往会停留足够长的时间以进入终身代。 【参考方案1】:假设你只解析文档,不同解析器标准的排名如下:
1. StAX 是最快的
事件报告给你2。 SAX 是下一个
StAX 所做的一切,以及自动实现的内容(元素名称、命名空间、属性...)3. DOM 是最后一个
它完成了 SAX 所做的一切并将信息呈现为 Node 的实例。您的用例
如果需要维护所有的 XML,DOM 是标准表示。它与 XSLT 转换 (javax.xml.transform)、XPath (javax.xml.xpath) 和模式验证 (javax.xml.validation) API 完美集成。但是,如果性能是关键,您可以使用 StAX 构建自己的树结构,速度比 DOM 解析器构建 DOM 的速度要快。【讨论】:
嗯,你觉得“事件上报给你”和“内容自动实现”会发生什么? StAX 将报告该元素已启动,如果您从不询问元素名称或 URI,则该数据无需实现为 String 对象。另一方面,SAX 解析器会将数据作为字符串对象作为事件的一部分来实现。 也许吧。如果你告诉我你看过 StaX 的内部结构,它是围绕基于字符的状态机构建的,我相信你。但是,我希望它会在内部生成令牌,即使您从不要求它们。 我从未看过 StAX 解析器的内部结构。如果您只考虑命名空间 URI 方面。已实现的令牌可以是“foo:bar”。 SAX 解析器会将“foo”前缀解析为命名空间 URI 并报告它,StAX 解析器不需要针对令牌执行该工作,因此执行速度更快。【参考方案2】:DOM 解析需要你将整个文档加载到内存中,然后遍历一棵树来找到你想要的信息。
SAX 只需要执行基本 IO 所需的内存,并且可以在读取文档时提取所需的信息。因为 SAX 是面向流的,所以您甚至可以处理仍在由另一个进程写入的文件。
【讨论】:
是的,我明白这一点。我的问题是“为什么 sax 解析更快?”不是“sax 和 dom 有什么区别?” @Stargazer712 - mikerobi 的回答没有解决我的问题。我怀疑他/她甚至读过这个问题。这是对任何 dom/sax 问题的死记硬背。如果有人愿意花时间提供深思熟虑的答案,我会持开放态度。 @andersonbd1,我准备好了你的问题,很抱歉你没有理解我的回答。对我来说很明显,一个需要更多内存并且在完全解析之前不会让您访问数据的进程将比需要非常少内存并且允许您访问数据的速度几乎与它一样快的进程慢可以阅读。 @andersonbd1,读了你的问题,在我看来你真的不明白 SAX 和 DOM 之间的区别,这是你不知道答案的一个因素题。鉴于此,mikerobi 的回答是有道理的。您可能确实了解其中的区别,但您的问题并不清楚。没有必要声称他没有阅读问题或给出轻率的答案。 @mikerobi - 我很抱歉声称你没有阅读这个问题。我有点防御,因为我被指控没有“开放的心态”。但是这出戏就够了——在我看来,需要内存不需要 2.5 毫秒。我可以在更短的时间内完成更多的内存密集型操作。【参考方案3】:SAX 更快,因为 DOM 解析器通常使用 SAX 解析器在内部解析文档,然后执行创建和操作对象以表示每个节点的额外工作,即使应用程序并不关心它们。
直接使用 SAX 的应用程序可能比 DOM“解析器”更有效地利用信息集。
StAX 是一种令人愉快的媒介,应用程序可以获得比 SAX 的事件驱动方法更方便的 API,但不会遭受创建完整 DOM 效率低下的问题。
【讨论】:
【参考方案4】:SAX 比 DOM 快(通常在读取大型 XML 文档时会感觉到),因为 SAX 以事件序列的形式为您提供信息(通常通过处理程序访问),而 DOM 创建节点并管理节点创建结构,直到 DOM 树完全已创建(如 XML 文档中所示)。
对于相对较小的文件,您不会感觉到效果(除了可能由 DOM 完成额外处理以创建节点元素和/或节点列表)。
我无法对 StAX 发表评论,因为我从未玩过它。
【讨论】:
以上是关于为啥 sax 解析比 dom 解析快?以及 stax 是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章