一、概述
VTD-XML是一种无提取的XML解析方法,它较好的解决了DOM占用内存过大的缺点,并且还提供了快速的解析与遍历、对XPath的支持和增量更新等特性。
二、原理
为了实现non-extractive(非提取)这个目的,它将原XML文件原封不动的以二进制的方式读进内存,连解码都不做,然后在这个二进制byte数组上解析每个 element的位置并把一些信息记录下来,这种记录就被成为VTD(Virtual Token Descriptor,虚拟令牌描述符)。
之后的遍历操作便在这些保存下来的记录上进行,如果需要提取XML内容就利用记录中的位置等 信息在原始byte数组上进行解码并返回字符串。
VTD(Virtual Token Descriptor,虚拟令牌描述符)结构:
VTD是一个64bits定长的数值类型,记录了每个元素的起始位置(offset),长度(length),深度(depth)以及令牌(元素标签)的类型(type)等信息。
如下图,表示了每个元素的位置及类型信息,对Xml的所有操作都是基于这个数据结构:
它是二进制格式规范,而不是API规范
VTD记录是原始数据类型(32位的整数倍),它编码XML文件中令牌的以下参数:
- 开始偏移
- 长度
- 嵌套深度
- 令牌类型
VTD要求XML文档在内存中保持不变。
我们当前的VTD记录布局进一步指定了以下内容:
- 使用64位作为基元类型(b63~b0)
- 大端
- 起始偏移:30位(b29~b0)最大值为2 ^ 30 -1 = 1G -1
- 长度:20位(b51~b32)最大值为2 ^ 20-1 = 1M -1
- 对于某些令牌类型
- 前缀长度:9位(b51~b43)最大值511
- Q名长度:11位(b42~b 32)最大值1023
深度:8位(b59~b52)最大值为2 ^ 8-1 = 255
令牌类型:4位(b63~b60)
保留位:2位(b31:b30)
单位 - 因为处理模型在内部存储未解码的XML,所以偏移和长度的单位是编码格式的原始字符。对于UTF-8和ISO-8859,长度和偏移量以字节为单位。对于UTF-16,它们是16位字。
三、VTD的优点和缺点
由于VTD记录的长度不变,因此基于VTD的XML处理可能具有以下优点:
节省内存:
- 由于VTD记录不是对象,因此不受每个对象内存开销的影响。
- VTD存储可以批量分配(即使用大内存块):当分配一个大内存块来存储1024个VTD令牌时,只会产生一次每阵列内存开销,从而大大减少了每个记录的开销。几乎没有。
高性能:
- 使用VTD,我们尝试在解析中实现高性能,这是VTD内存节省功能的副产品:更少的内存使用意味着分配的内存量更少。
- 大型内存块的分配和GC比许多离散对象更快。请记住,我们处于这项技术的早期阶段。因此,应该期望在性能和可用性方面进一步改进。
固有持久性:
- VTD记录可以保存在磁盘上或沿XML传输,以提高XML处理吞吐量。
增量更新:
- 此功能在最近的文章中有详细解释
同时,需要了解VTD的一些局限性:
各种字段的上限:
- (1)对于起始标记(最大Qname长度为2048;前缀512),溢出条件导致解析异常。对于其他令牌(上限为1M),可能会将长令牌分成多个较短的令牌。
- (2)深度字段溢出条件会导致解析异常。
- (3)起始偏移:目前支持的最大文档是1G字符(1G字节或2G字节,具体取决于实际的文档编码)。
位级布局的限制:
- 可能需要重新排列位级布局以满足实际处理要求。
VTD令牌长度限制:
- 当前VTD记录的长度为64位。如果64位不够,可以添加另一个32位。
四、VTD-XML与DOM和SAX对比
与DOM相比,VTD-XML显着更快(高达10倍),内存效率更高(高达5倍)。
与SAX / PULL相比,VTD-XML不仅速度更快,而且能够随机访问,因此更易于使用。
五、FAQ
VTD-XML是索引器还是解析器?
VTD-XML同时是解析器和索引器,因为VTD-XML的API直接使用VTD索引来实现解析的目的。
为什么我应该将VTD-XML用于大型XML文件?
由于众多原因总结如下:
性能:VTD-XML的性能远远优于SAX
易于使用:随机访问与XPath结合使应用程序易于编写
更好的可维护性:应用程序代码更短,更易于理解。
增量更新:偶尔的小变化变得非常有效。
索引:预解析形式的XML将进一步提高处理性能。
内存映射:扩展的VTD-XML可以选择内存映射XML文档,从而可以处理大小大于可用物理内存的XML文件。
其他功能:只能使用VTD-XML剪切,粘贴,拆分和组合XML文档。
为了利用VTD-XML,我们建议开发人员将超大型XML文档拆分为更小,更易于管理的卡盘(<2GB)。
自VTD-XML 2.4以来,XimpleWare引入了一个扩展版本的VTD-XML,能够处理大小达256 GB的XML文档。
VTD-XML如何实现随机访问?
通过使用位置缓存(LC),它们本质上是分层元素目录。
位置缓存按每个级别分配; 即,相同的LC索引相同嵌套深度的所有元素。 LC条目是64位整数,其高32位是元素(开始标记)的VTD记录的索引值,并且其低32位指向对应于第一子元素的LC条目。
动机是坚持VTD的获胜策略:恒定令牌长度和固有持久性。
结果:LC成本约为总VTD-XML处理成本的* 10%*。
如果我获得属性名称的VTD索引值,我该如何检索属性值?
如果属性名称的索引值是i,则属性值对应于i + 1。