一般当我们提起XML的运用时,最头痛的部份就是XML的verbosity与XML的剖析速率,当须要处置惩罚大XML文件时这个题目便变得分外严峻。我在这里说起的,就是怎样优化XML处置惩罚速率的话题。
当我们挑选处置惩罚XML文件的时刻,我们大抵上有两种挑选:
DOM,这是W3C的规范模子,它将XML的构造信息以树形的体式格局构建,供应了遍历这颗树的接口与要领。
SAX,一种初级的parser,逐元素的向前只读处置惩罚,不含有构造信息。
以上两种挑选都各有利弊,然则都不是迥殊好的处理方案,它们的优瑕玷以下:
DOM
长处:易用性强,因为一切的XML构造信息都存在于内存中,而且遍历简朴,支撑XPath。
瑕玷:Parsing速率太慢,内存占用太高(原文件的5x~10x),关于大文件来讲险些不可能运用。
SAX
长处:Parsing速率快,内存占用不与XML的大小相联系(可以做到XML涨内存不涨)。
瑕玷:易用性差,因为没有构造信息,而且没法遍历,不支撑XPath。假如须要构造的话只能读一点构造一点,如许的可维护性迥殊的差。
我们可以看出,基本上DOM与SAX是恰好相反的两个极度,然则任何一个都不能很好的满足我们的大部份请求,我们须要找出别的一种处置惩罚要领来。注重XML的效力题目并非XML自身的题目,而是处置惩罚XML的Parser的题目,就像我们在上面看到的两种要领有差别的效力衡量一样。
思索
我们很喜欢相似DOM的运用要领,因为我们可以遍历,这意味着可以支撑XPath,大大增强了易用性,然则DOM的效力很低。就像我们已晓得,效力题目出在处置惩罚机制上。那末,DOM到底有哪些方面影响了它的效力呢?下面让我们来做一个周全的剖解:
在现今大多数基于虚拟机(托管,或任何相似机制)手艺的平台下,对象的建立烧毁是一个耗时的功课(这里值得主如果Garbage Collection的耗时),DOM机制中所运用的大批的对象建立烧毁无疑是影响其效力的缘由之一(会激发过量的Garbage Collection)。
每一个对象都邑分外有32bits用来存储它的内存地址,当像DOM一样具有大批对象的时刻这个分外开支也是不小的。
引发以上两个题目标最重要的效力题目在于,DOM与SAX都是extractive parsing形式,这类剖析形式必定了DOM与SAX都须要大批的建立(烧毁)对象,引发效力题目。所谓的extractive parsing就是说在剖析XML时,DOM或SAX会提取一部份原文件(一般来讲是一个字符串),然后在内存中举行剖析构建(输出天然就是一个或一些对象了)。拿DOM这个例子来讲,DOM会将每一个element, attribute, PRocessing-instruction, comment等等都剖析成对象并授与构造,这就是所谓的extractive parsing。
由extractive的题目带来的另一个题目就是更新效力,在DOM中(SAX因为不支撑更新所以基础不提它),每一次须要做修正时,我们要做的就是将对象的信息再剖析回XML的字符串,注重这个剖析是个完全的剖析,也就是说,原文件并没有被运用,而是直接将DOM模子从新完全剖析成XML字符串。换句话讲,也就是DOM并不支撑Incremental Update(增量更新)。
另一个极可能不被注重到的“小”题目就是XML的编码,无论是何种剖析要领都须要可以处置惩罚XML的编码,也就是说,在读取的时刻解码,在写入的时刻编码。DOM的另一个效力题目就是当我关于一个大XML只想做很小的一起修正的时刻它也必需首先将全部文件举行解码,然后构建构造。无形中又是一个开支。
让我们来总结一下题目,简朴的讲DOM的效力题目重要出在它的extractive parsing形式上(SAX也是一样,有一样的题目),由此激发了一系列相干题目,假如可以击破这些效力瓶颈的话那末可以设想XML的处置惩罚效力将进一步的获得进步。假如XML的易用性与处置惩罚效力获得奔腾性的进步的话,那末XML的运用局限,运用形式将获得更一步的升华,也许由此可以发生出许很多多精彩的之前连想都没有想过的基于XML的产物来。
前途
VTD-XML就是对以上题目标思索后给出的答案,它是一个non-extractive XML parser,因为它精彩的机制,很好的处理(防止)了上面所提出的种种题目,而且还“趁便”带来了non-extractive的其他优点,像疾速的剖析与遍历、XPath的支撑、Incremental Update等等。我这里有一组数据,取自于VTD-XML的官方网站:
VTD-XML的剖析速率是SAX(with NULL content handler)的1.5x~2.0x。With NULL content handler的意义就是说SAX剖析中没有插进去任何分外的处置惩罚逻辑,也就是SAX的最高速率。
VTD-XML的内存占用是原XML的1.3x~1.5x(个中1.0x的部份是原XML,0.3x~0.5x是VTD-XML占用的部份),而DOM的内存占用则是原XML的5x~10x。举一个例子,假如一个XML的大小是50MB,那末用VTD-XML读取进来内存占用会在65MB~75MB之间,而DOM的内存占用则会在250M~500MB之间。基于这个数据用DOM处置惩罚大的XML文件险些是不可能的挑选。
你可能会以为难以设想,真的可以做出比DOM易用性还好,比SAX还快的XML剖析器吗?别急着下定论,照样来看看VTD-XML的道理吧!
基本道理
就像大多数好的产物一样,VTD-XML的道理并不庞杂,而是很奇妙。为了完成non-extractive这个目标,它将原XML文件一成不变的以二进制的体式格局读进内存,连解码都不做,然后在这个byte数组上剖析每一个element的位置并把一些信息记录下来,以后的遍历操纵便在这些保留下来的record上举行,假如须要提取XML内容就运用record中的位置等信息在原始byte数组上举行解码并返回字符串。这一切看起来都很简朴,然则,这个简朴的历程确有多个机能细节在里边,而且隐蔽了若干个潜伏的才能。下面我们首先来形貌一下各个机能细节:
为了防止过量的对象建立,VTD-XML决议采纳原始的数值范例作为record的范例,如许便可以没必要用heap。VTD-XML的record机制就叫做VTD(Virtual Token Descriptor),VTD将机能瓶颈在tokenization阶段就处理掉了真的是很奇妙很专心的做法。VTD是一个64bits长度的数值范例,记录了每一个element的肇端位置(offset),长度(length),深度(depth)以及token的范例(type)等信息。
注重VTD是牢固长度的(官方决议用64bits),如许做的目标就是为了进步机能,因为长度牢固,在读取,查询等操纵的时刻分外的高效(O(1)),也就是可以用数组这类高效的构造来构造VTD大大减少了因为大批运用对象而发生的机能题目。
VTD的超才能(一点都不夸大地说)就在于它可以将XML这类树形的数据构造简朴的变更成对一个byte数组的操纵,任何你能设想到的关于byte数组的操纵都可以运用在XML上了。这是因为读取进来的XML是二进制的(byte数组),而VTD则记录了每一个element的位置等接见用信息,当我们找到要操纵的VTD的时刻,只需用offset与length等信息便可以对原始byte数组举行任何操纵,或许可以直接对VTD举行操纵。举例来讲,我想在一个大XML中找出一个element并删除它,那末我只须要找到这个element的VTD(遍历要领稍候再讲),将这个VTD从VTD数组中删除,然后再运用一切的VTD写出到另一个byte数组中便可以了,因为删除的VTD标清楚明了要删除的element的位置,所以在新写入的byte数组中就不会涌现这段element了,用VTD写入新的byte数组实际上就是一个byte数组的拷贝,其效力相称的高,这就是所谓的增量更新(incremental update)。
关于VTD-XML的遍历体式格局,它采纳了LC (Location Cache),简朴地说就是将VTD以其深度作为规范构建的一个树形的表构造。LC的entry也是64bits长的数值范例,前32bits代表一个VTD的索引(index),后32bits代表了这个VTD的第一个child的索引。运用这些信息便可以计算出任何一个你想要抵达的位置了,关于详细的遍历要领请参看官方网站的文章。基于这类遍历体式格局的VTD-XML有与DOM差别的操纵接口,这是可以明白的,而且,VTD-XML的这类遍历体式格局可以在起码的几步内将你带到你所须要的处所去,遍历的机能非常凸起。
总结
就像你上面看到的,VTD-XML有着诱人的特征,而如今的1.5版本中已加入了XPath的支撑(只需可以遍历,便可以支撑XPath,这是日夕的事:-)),它的实用性已逾越了现今我们所设想的局限了。另一个VTD-XML的超才能,就是基于它如今的处置惩罚体式格局,完全可以支撑未来的Binary XML规范,并经由过程Binary化将XML的运用推向更高一层楼!这也是我目前所期待的!:-)
不过,VTD-XML依然有很多须要革新与完美的处所,这方面值得我们勤奋与讨论。
以上就是新兴XML处置惩罚要领VTD-XML引见的内容,更多相干内容请关注ki4网(www.ki4.cn)!