• 张琳   2014/7/24 13:44:00
  • 为什么LINQ to XML的性能要优于XmlDocument?
  • 关键字: LINQ XML 延迟执行
  •  今天群里有人问如何解析web.config方便,然后我就推荐了Linq to XML,然后就有人说“我宁可XmlDocument,再SeleteNodes和SeleteNode”,不要用LINQ之类的,甚至否定EntityFramework等一系列框架,认为这些都是所谓的“懒人技术”,都是以牺牲性能为代价的。我在这里想申明一点,没有测试就没有发言权,并不是所有的”懒人技术“都是以牺牲性能为代价的。我这人比较喜欢就技术论技术,不喜欢武断的言论,于是展开了讨论。本文只是做一个总结。


    为什么LINQ to XML性能优于XmlDocument?

    首先,我们需要明白的一点是:

    LINQ to XML有一位优秀的母亲——XmlReader。

    LINQ to XML 在 XmlReader 基础之上实现的,也就是LINQ to XML源于XmlReader,高于XmlReader。

    遗传基因很重要!

    XmlReader 是一种快速的只进非缓存分析器。他丫的对XML 数据流的访问是只读的。


    其次,LINQ to XML有一位出色的父亲——Linq。

    LINQ to XML 的一个最重要的性能优势(与 XmlDocument 相比)为:LINQ to XML 中的查询是静态编译的,而 XPath 查询则必须在运行时进行解释。

    这个因素是性能中至关重要的,所谓”子不教,父之过“!

    也就是说,LINQ to XML的查询被编译成静态链接的方法调用,这样的性能提升是巨大的。反观XmlDocument,它在每次调用 SelectNodes 方法时,都必须在内部执行以下操作:
    1.分析包含 XPath 表达式的字符串,并将字符串划分成多个标记。
    2.验证这些标记以确保 XPath 表达式有效。
    3.将表达式转换为内部表达式树。
    4.循环访问节点,为基于表达式计算的结果集选择适当的节点。

    与相应的 LINQ to XML 查询完成的工作相比,这需要执行非常多的工作。

    除此之外,LINQ to XML还继承了父亲的延迟执行的优良传统,也能够提高性能。

    父亲这么优秀,XmlDocument自然无法相比了。

    所以,富二代和官二代起点就比你高,你如果不比他们多付出N倍的努力,你甚至连他们的起点都无法到达。

    科普下延迟执行的知识:

    延迟执行意味着表达式的计算延迟,直到真正需要它的实现值为止。 当必须操作大型数据集合,特别是在包含一系列链接的查询或操作的程序中操作时,延迟执行可以大大改善性能。 在最佳情况下,延迟执行只允许对源集合的单个循环访问。 
    LINQ 技术广泛应用了延迟执行,包括在核心 System.Linq 类的成员和不同 LINQ 命名空间中的扩展方法(如 System.Xml.Linq.Extensions)中使用。

    除了上面的,其他的还有些他在成长过程中,自己提升的优点,比如:XName 和 XNamespace 对象是原子化的,如果这两个对象包含相同的名字,则它们会引用同一个对象。 也就是说当比较两个原子化名称是否相等时,只需确定这两个引用是否指向同一个对象,而不必进行很”耗费时间“的字符串比较,这个是有助于性能提升的。


    尾声

    虽然这不是拍电影,但是尾声还是必须的。
    1.没有测试就没有发言权,并不是所有的”懒人技术“都是以牺牲性能为代价的。
    2.虽然Linq to SQL的名声不大好,但是LINQ to XML却应该是实至名归。而且Linq to SQL的儿子EF正在挽回她的名声,如果你没用过,请不要说他不行,如果你用的不当,请也别说他不行。
    3.懒人技术都是懒人发明的,但是往往就是这些懒人推动了技术的前进。
    4.每一种技术和框架都是有使用场景的,如果你用错了场景,请不要说他不行。
    5.合理把控性能,在大多数非苛刻场景,不到1毫秒甚至更多的差别,你完全不必要浪费1小时以上的精力,认真提高开发效率才是关键的。比如枚举类型的ToString()。