专栏首页magicodes为什么LINQ to XML的性能要优于XmlDocument?

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

一直很忙,压了很多贴,今天发一篇吧。后面的看心情吧。

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

LINQ to XML的性能测试

很多同学已经做过性能测试了,我就不重复了,如下链接:

XML数据读取方式性能比较(一)

XML数据读取方式性能比较(二)

从上面的结果我们不能看出,Linq to Xml的性能明显是优于XmlDocument的。我这人比较喜欢追根溯源,如果单从这个,总是有人会产生各种悖论,比如:

【码帅】-------- 13:52:01 确定真是LINQ高吗 【码奴】-------- 13:52:32 什么高? 【码帅】-------- 13:52:42 为什么上面2个都有Add 【码帅】-------- 13:52:49 下面2个都没有 【码帅】-------- 13:52:54 这测试公正吗 【码帅】-------- 13:53:18 好比一个是直接new Object[] 【码帅】-------- 13:54:38 4个测试就有问题 【码帅】-------- 13:56:03 2个40多秒的都有这Add

其实他的问题都没到点上,这里根本就不是Add的问题,Linq的ToList()方法肯定也干了这事,如果怀疑这里,完全可以自己去写个测试。所以我觉得有必要说下为什么LINQ to XML性能优于XmlDocument的缘由了。

为什么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()。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 使用Flash上传应该注意的问题。

              使用Flash上传在IE是没问题的,但是在几乎所有的非IE内核浏览器几乎都会遇到一个问题,那就是处理上传的页面或代码无法获取Cookie。不...

    雪雁-心莱科技
  • Magicodes.IE 2.0发布

    Magicodes.IE是我们维护的开源的导入导出通用库,去年年底已加入NCC开源组织。

    雪雁-心莱科技
  • 构建自己的简单微服务架构(开源)

    本篇仅作引导,内容较多,如果阅读不方便,可以使用电脑打开我们的文档官网进行阅读。如下图所示:

    雪雁-心莱科技
  • 从零开始学习PYTHON3讲义(十三)记事本的升级版:网络记事本

    网络编程的火热和重要性这里就不多说了,我们直接来看看Python在互联网编程方面的表现。

    俺踏月色而来
  • Symfony 服务容器:使用建造者创建服务

    本文是依赖注入(Depeendency Injection)系列教程的第 5 篇文章,本系列教程主要讲解如何使用 PHP 实现一个轻量级服务容器,教程包括:

    柳公子
  • Symfony 服务容器:使用 XML 或 YAML 文件描述服务

    本文是依赖注入(Depeendency Injection)系列教程的第 5 篇文章,本系列教程主要讲解如何使用 PHP 实现一个轻量级服务容器,教程包括:

    柳公子
  • 吉林大学软件工程数据库应用db2课程的复习资料

    大家好,这里是星辉,你们的16级学长,这是我们复习时用到的所有的复习资料,希望能够大家能够用到。

    星辉
  • Redux 入门教程(一):基本用法

    一年半前,我写了《React 入门实例教程》,介绍了 React 的基本用法。 React 只是 DOM 的一个抽象层,并不是 Web 应用的完整解决方案。有两...

    ruanyf
  • Python用Django写restful api接口

    用Python如何写一个接口呢,首先得要有数据,可以用我们在网站上爬的数据,在上一篇文章中写了如何用Python爬虫,有兴趣的可以看看:

    六月的雨
  • 基于运动的视频插帧技术

    Kokaram首先对视频插帧技术的背景、目标进行了介绍,并以单帧插值为例解释了帧插值实际上就是运动插值的过程。同时对近年出现的基于卷积神经网络的方法进行了分析,...

    用户1324186

扫码关注云+社区

领取腾讯云代金券