文章目录

  • 零、背景前提
  • 一、Qt - QDomDocument
    • 1)测试代码
    • 2)测试结果
  • 二、TinyXml(略)
  • 三、TinyXml2
    • 1)测试代码
    • 2)运行效果及结论
  • 四、RapidXml
    • 1)解析测试
    • 2)测试效果
  • 五、PugiXml
    • 1)测试代码
    • 2)测试结果解析
  • 六、总结
  • 七、tinyxml与tinyxml2的对比
    • 1)作者更新的原因
    • 2)区别
    • 3)更加人话的区别

零、背景前提

通常我们在一些软件的初始化或者保存配置时都会遇到对XML文件的操作,包括读写xml文件,解析内容等等。在我的工作中就遇到了这么一个问题,就是在ARM平台下Qt解析xml文件非常的慢,最初怀疑是我的操作有问题或者是ARM平台下的文件操作本身就很慢,于是就开始调查到底是哪里的效率问题,下面是一些测试分享给大家

  • 效率比较低的代码
QString filename = "...";
QFile file( filename );//< step1 open file
if( !file.open(QIODevice::ReadOnly) )
{qDebug() << "failed in opening file!";return false;
}//< step2 read file content
QDomDocument doc;       //< #include <qdom.h>
if( !doc.setContent( &file ) )
{qDebug() << "failed in setting content!";file.close();return false;
}
file.close();
...  //< operations on the content of file!
  • 运行速度慢的原因
    起初以为是文件打开和关闭耗时太多,所以在文件open和close函数前后都获取了系统时间来测试了函数消耗时间,结果是耗时很短,反而是 doc.setContent 耗费了非常长的时间,这才发现原来是Qt获取XML文件内容且Dom模型结构花费了太多时间,所以我们开始寻求效率更高的解决方案。

  • 测试环境

Windows:
system:windows 10
cpu: intel core-i5-5200u @2.2GHz
IDE: visual studio 2010
compiler: VC10Linux:
system: Debian 4.4.5-8
cpu: intel core-i5-3450 @3.3GHz
IDE: VIM
compiler: gcc version 4.4.5--Qt版本: 4.8.4
--用来测试的文件名为 DriverConfig.xml,大小为245Kb,共1561行,大部分内容为中文
--比较项有 TinyXml2, QDomDocument,因为从接口来看这两者的操作方式很类似,后面我会加入其它的xml解
析库的比较,如 xmlbooster 等。

一、Qt - QDomDocument

下面是利用Qt中的xml支持来读取文件内容的源代码:

1)测试代码


#include <QtCore/QCoreApplication>
#include <qdom.h>
#include <QFile>
#include <QIODevice>
#include <iostream>
#ifdef Q_OS_WIN
# include <Windows.h>
#else
# include <sys/time.h>
#endifusing std::cout;
using std::endl;#define TEST_TIMES 10int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);#ifdef Q_OS_WIN  //< windowslong tStart = 0;long tEnd   = 0;LARGE_INTEGER nFreq;LARGE_INTEGER nStartTime;LARGE_INTEGER nEndTime;double time = 0.;QueryPerformanceFrequency(&nFreq);QFile file( "D:/DriverConfig.xml" );QDomDocument doc;for( int i = 0; i < TEST_TIMES; ++i ){doc.clear();//< step1 open fileif( !file.open(QIODevice::ReadOnly) ){cout << "failed to open file!" << endl;continue;}Sleep( 100 );QueryPerformanceCounter(&nStartTime); //< step2 set contentif( !doc.setContent(&file) ){cout << "Failed to read xml file!" << endl;}QueryPerformanceCounter(&nEndTime);time = (double)(nEndTime.QuadPart-nStartTime.QuadPart) / (double)nFreq.QuadPart * 1000.;  //< mscout << " seting content costs " << time << "ms" << endl;file.close();Sleep( 100 );}#else //< LINUXtimeval starttime, endtime;QFile file( "/home/liuyc/DriverConfig.xml" );QDomDocument doc;double timeuse = 0.;double timeAverage = 0.;for( int i = 0; i < TEST_TIMES; ++i ){doc.clear();//< step1 open fileif( !file.open(QIODevice::ReadOnly) ){cout << "failed to open file!" << endl;continue;}sleep( 1 );  //< delay for 1sgettimeofday( &starttime, 0 );//< step2 set contentif( !doc.setContent(&file) ){cout << "Failed to read xml file!" << endl;continue;}gettimeofday( &endtime, 0 );timeuse = 1000000. * (endtime.tv_sec - starttime.tv_sec) + endtime.tv_usec - starttime.tv_usec;timeuse *= 0.001 ;timeAverage += timeuse;cout << " reading files costs : " << timeuse << "ms" << endl;file.close();sleep( 1 );  //< delay for 1s}timeAverage /= TEST_TIMES;cout << " The End *****************\n    average costs = " << timeAverage << "ms" << endl; #endifreturn a.exec();
}

2)测试结果

  • 下面来看看windows下的运行结果:

    为什么同一个函数读同一个文件十次会有这么大的差异所以我才会在文件打开和关闭时分别都加了延时,希望避免文件开关的过程对这个函数产生的影响,结果依然没有解决这个问题
  • 那下面我们来看linux下的运行结果:

    显然,linux下这个时间相对的稳定可信,所以我们后面的测试也只要以linux下的时间作为参考。

二、TinyXml(略)

三、TinyXml2

下面我们来看利用tinyxml2实现读取的源代码:

1)测试代码

#include <iostream>
#include "tinyxml2.h"
#ifdef _WIN32
#include <Windows.h>
#else
#include <sys/time.h>
#endif
using namespace tinyxml2;
using std::cout;
using std::endl;#define TEST_TIMES  10int main()
{
#ifndef _WIN32  //< linux ------------------------------------------------tinyxml2::XMLDocument doc;timeval starttime, endtime;double timeuse = 0.;double timeAverage = 0.;for( int i = 0; i < TEST_TIMES; ++i ){gettimeofday( &starttime, 0 );if( XML_SUCCESS != doc.LoadFile( "/home/liuyc/DriverConfig.xml" ) ){cout << "failed in load xml file! _ " << i << endl;continue;}gettimeofday( &endtime, 0 );timeuse = 1000000. * (endtime.tv_sec - starttime.tv_sec) + endtime.tv_usec - starttime.tv_usec;timeuse *= 0.001 ;cout << " reading files costs : " << timeuse << "ms" << endl;timeAverage += timeuse;}timeAverage /= TEST_TIMES;cout << " \n** The end *******************\n    the average costs = " << timeAverage << "ms" << endl;#else  //< windows ---------------------------------------------------LARGE_INTEGER nFreq;LARGE_INTEGER nStartTime;LARGE_INTEGER nEndTime;double time = 0.;QueryPerformanceFrequency(&nFreq);tinyxml2::XMLDocument doc;for( int i = 0; i < TEST_TIMES; ++i ){QueryPerformanceCounter(&nStartTime); if( XML_SUCCESS != doc.LoadFile( "D:/DriverConfig.xml" ) ){cout << "failed in load xml file! _ " << i << endl;continue;}QueryPerformanceCounter(&nEndTime);time = (double)(nEndTime.QuadPart-nStartTime.QuadPart) / (double)nFreq.QuadPart * 1000.;  //< mscout << " reading files costs : " << time << "ms" << endl;}cout << endl;system("pause");#endif  //< end of windows ---------------------------------------------------return 0;
}

2)运行效果及结论

  • linux结果
    接下来先看linux下的运行结果(windows下的运行结果已经没有太多参考价值了)

  • 结论
    linux下的表现依然很稳定,这里我们可以得出一个很明显的结论,tinyxml的处理效率要比QDomDocument的处理效率高很多(这里的数据大致是4倍,但不包括对于xml文件内部信息的处理的其他函数接口的调用)。

  • win结果
    看一下windows下的测试结果:

    这里效率也明显的比Windows Qt提升很多,而且执行时间也相对稳定了一,所以前一个测试中运行时间十分不稳定的情况暂定为Qt本身实现的问题,具体是什么问题或者在高版本的Qt里面是否已解决尚无答案。

四、RapidXml

注:RapidXml版本: 1.13
在RapidXml Manual的介绍中可以看到它和TinyXml以及其他的一些xml解析库做了对比(这里面tinyXml是最慢的),原文中介绍这是目前Xml解析最快的

  • 官方备注

As a rule of thumb, parsing speed is about 50-100x faster than Xerces DOM, 30-60x faster than TinyXml, 3-12x faster than pugxml, and about 5% - 30% faster than pugixml, the fastest XML parser I know of.

1)解析测试

#include <iostream>
#include "rapidxml.hpp"
#include "rapidxml_print.hpp"
#include "rapidxml_utils.hpp"
#ifdef _WIN32
# include <Windows.h>
#else
# include <sys/time.h>
#endifusing namespace rapidxml;
using std::cout;
using std::endl;#define TEST_TIMES  10int main()
{
#ifdef _WIN32  //< windowsLARGE_INTEGER nFreq;LARGE_INTEGER nStartTime;LARGE_INTEGER nEndTime;double time = 0.;QueryPerformanceFrequency(&nFreq);//< parse xmlfor( int i = 0 ; i < TEST_TIMES; ++i ){rapidxml::file<> filename( "D:/DriverConfig.xml" );xml_document<> doc;QueryPerformanceCounter(&nStartTime); doc.parse<0>( filename.data() );QueryPerformanceCounter(&nEndTime);time = (double)(nEndTime.QuadPart-nStartTime.QuadPart) / (double)nFreq.QuadPart * 1000.;  //< mscout << " reading files costs : " << time << "ms" << endl;doc.clear();}system("pause");#elsetimeval starttime, endtime;double timeuse = 0.;double timeAverage = 0.;//< parse xmlfor( int i = 0 ; i < TEST_TIMES; ++i ){rapidxml::file<> filename( "/home/liuyc/DriverConfig.xml" );xml_document<> doc;gettimeofday( &starttime, 0 );doc.parse<0>( filename.data() );gettimeofday( &endtime, 0 );timeuse = 1000000. * (endtime.tv_sec - starttime.tv_sec) + endtime.tv_usec - starttime.tv_usec;timeuse *= 0.001 ;cout << " reading files costs : " << timeuse << "ms" << endl;doc.clear();timeAverage += timeuse;}timeAverage /= TEST_TIMES;cout << " \n** The end *******************\n    the average costs = " << timeAverage << "ms" << endl;#endifreturn 0;
}

2)测试效果

  • 同样,先看linux下运行的结果:

    效率确实为 TinyXml2 的2.x倍,但是并没有像 rapidXml 的说明手册里说的有30~60倍的效率差异(手册中是和TinyXml比较的,而不是TinyXml2)。在我自己初步的使用来看,我觉得 RapidXml 的接口并没有有 Qt 和 TinyXml2 那么简单易用,所以在文件大小不大或对效率要求不是很极限的情况下,使用 TinyXml2 可能会获得开发效率和运行效率的双赢。

  • 再来看一下windows下的运行结果:

    依然不是很稳定,所以只做参考。

五、PugiXml

更新日期 2017.05.03

经博友提醒,现添加pugixml的测试,为节省篇幅只贴出 linux 下的测试代码(代码与 tinyxml 非常相似),可以看到pugixml与tinyxml的调用方式很相似!

1)测试代码

#include <iostream>
#include "pugixml.hpp"
#include "pugiconfig.hpp"
#include <sys/time.h>
using namespace std;#define TEST_TIMES 10int main( void )
{pugi::xml_document doc;timeval starttime, endtime;double timeuse = 0.;double timeAverage = 0.;for( int i = 0; i < TEST_TIMES; ++i ){gettimeofday( &starttime, 0 );if( !doc.load_file( "/home/liuyc/DriverConfig.xml" ) ){cout << "failed in load xml file! _ " << i << endl;continue;}gettimeofday( &endtime, 0 );timeuse = 1000000. * (endtime.tv_sec - starttime.tv_sec) + endtime.tv_usec - starttime.tv_usec;timeuse *= 0.001 ;cout << " reading files costs : " << timeuse << "ms" << endl;timeAverage += timeuse;}timeAverage /= TEST_TIMES;cout << " \n** The end *******************\n    the average costs = " << timeAverage << "ms" << endl;return 0;
}

2)测试结果解析

结果也正如博友所说,pugixml的效率甚至比rapidxml也明显快了不少!

六、总结


工作以来基本上都是在Qt下开发,深切体会到Qt的接口封装很完善易用,但不可避免的牺牲了一些效率(虽然没想到效率降低了这么多),相对的,tinyxml2和pugixml在接口上都与Qt非常相似,Pugixml的效率更是提升明显,所以目前xml的解析还是推荐Pugixml。后面我会继续仔细研究各类xml解析器的使用方法,再与大家分享!

七、tinyxml与tinyxml2的对比

原文链接传送门

1)作者更新的原因

TinyXML-1 served my needs for many years; but it uses memory inefficiently, and doesn’t perform as well as desired for mobile devices. I wanted an XML parser that was a little more modern, a little simpler (the “tiny” had been lost a little over the years), and was a good fit for Android.

2)区别

1)共同点
①简单的API,Simple to use with similar APIs.
②基于DOM解析,DOM based parser.
③对于utf-8字符的支持,UTF-8 Unicode support. http://en.wikipedia.org/wiki/UTF-8
2)tinyxml2的优势
①更少内存内配,Many fewer memory allocation (1/10th to 1/100th), uses less memory (about 40% of TinyXML-1), and faster (~5x on read).
②不需要stl的支持,No STL requirement.
③使用C++规范更好,包括良好的命名空间规范,More modern C++, including a proper namespace.
④Proper and useful handling of whitespace(这句话我没懂)
3)tinyxml1的优势
①能报道解析失败的位置信息,Can report the location of parsing errors.
②支持C++流读取和字符串,Support for some C++ STL conventions: streams and strings
③非常成熟和良好的调试模式优化,Very mature and well debugged code base(这句纯粹是吹捧吧)

3)更加人话的区别

①tinyxml
由于TinyXml在加载文件后,所有的节点都是重新分配内存,然后操作完clear后,所有内存都会被释放,因此性能的瓶颈都在加载文件的时候,
②tinyxml2
tinyxml2它里面实现了一个简单的内存池,当我们进行加载文件和clear操作时,都是在内存池上进行操作,减少了向系统申请和释放内存的时间,速度瞬间提高了好多.

服务器开发24补充:市面上一些xml第三方库解析速度的对比,tinyxml、tinyxml2、Qt、RapidXml、PugiXml,和tinyxml与tinyxml2的对比相关推荐

  1. 嵌入式开发有用的github上的开源代码库

    嵌入式开发有用的github上的开源代码库 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u011559046/article/details/80 ...

  2. stm32 薄膜键盘原理_市面上的笔记本键盘优缺点解析,看完秒懂

    大家在选购电脑时,很多人的关注重点都是笔记本的配置好不好.外观设计酷不酷和电池续航能力强不强,对电脑键盘往往不会太在意,其实一个好的电脑键盘也可以帮助你提高工作效率,特别对于小编这样的文字工作者,如果 ...

  3. 计算机键盘特点,市面上的笔记本键盘优缺点解析,看完秒懂!

    大家在选购电脑时,很多人的关注重点都是笔记本的配置好不好.外观设计酷不酷和电池续航能力强不强,对电脑键盘往往不会太在意,其实一个好的电脑键盘也可以帮助你提高工作效率,特别对于小编这样的文字工作者,如果 ...

  4. iOS常用第三方库大全,史上最全第三方库收集

    下拉刷新 EGOTableViewPullRefresh – 最早的下拉刷新控件. SVPullToRefresh – 下拉刷新控件. MJRefresh – 仅需一行代码就可以为UITableVie ...

  5. stm32 薄膜键盘原理_铅锤哥:市面上的笔记本键盘优缺点解析,看完秒懂

    点击上面↑ 玩转电脑 关注铅锤哥,轻松学电脑 本文转自电脑快科技网 笔记本电脑的键盘,虽然看起来都差不多,但是这小小的键盘也分成许多种不同的类型,今天我们就来系统的介绍一下不同种类的笔记本电脑键盘,以 ...

  6. 一些嵌入式开发有用的github上的开源代码库【转载-陶孜河畔】

    https://blog.csdn.net/u011559046/article/details/80172809 github 上部分开源代码库的地址,主要是嵌入式方向,包含其他的一些算法比如sla ...

  7. ios 开发日记 21 -自动处理键盘事件的第三方库:IQKeyboardManager

    我们写界面要考虑很多用户体验问题,键盘事件的响应就是比较麻烦的一种.我们需要监听键盘事件,考虑点击背景收起键盘.考虑键盘遮挡输入框问题等等,而且每个界面都要做这么一套.这个库帮我们解决了这个事情. 这 ...

  8. python xml第三方库_Python-XML库

    0 前言 XML即可扩展标记语言,XML是互联网数据传输的重要工具,它可以跨越互联网任何的平台,不受编程语言和操作系统的限制,可以说它是一个拥有互联网最高级别通行证的数据携带者. Python-基础篇 ...

  9. 在Ubuntu 16.04.5 LTS上使用python第三方库QRCode 6.0生成二维码实录

    简介 二维码简称 QR Code(Quick Response Code),学名为快速响应矩阵码,是二维条码的一种,由日本的 Denso Wave 公司于 1994 年发明.现随着智能手机的普及,已广 ...

最新文章

  1. (转载)新年——顺民的牢骚
  2. 【高并发解决方案】6、数据库水平切分的实现原理解析
  3. kickstart_具有Java Kickstart的MongoDB
  4. 图片上传下载连接云服务器tomcat
  5. mysql 时间_MySQL 日期时间
  6. 20200701:力扣194周周赛上
  7. lbp算法 matlab,lbp算法(lbp特征提取算法)
  8. vivado使用入门
  9. shell(30) : 批量修改文件后缀
  10. 时间序列分析|LSTM多变量时间序列预测
  11. idou老师教你学Istio 29:Envoy启动流程
  12. CF1463F Max Correct Set(取小样法+状压 DP)
  13. 全网最全编程学习网站汇总来了,还不赶快收藏
  14. 微信小程序云开发体会——总结软件工程导论大作业
  15. 原生js生成渐变色数组集合
  16. Linux驱动开发中的中间件:设备树
  17. 小米盒子打开adb调试模式
  18. BT.656、PAL、NTSC标准并行数据结构
  19. 【GPU】Nvidia CUDA 编程基础教程——利用基本的 CUDA 内存管理技术来优化加速应用程序
  20. 合理利用计算机虚拟内存,合理设置虚拟内存,目前8G内存足够日常使用

热门文章

  1. python pta 求出歌手的得分
  2. Multi-Metrics Graph-Based Unsupervised Domain Adaptation for Cross-Modal Hashing
  3. unity实现 魔兽争霸3地图拼接(例子)
  4. 谷歌官方流海适配方案
  5. CTFshow-菜狗杯-值覆盖-遍地飘零
  6. java ooa和ood_面向对象分析,设计,开发(OOA、OOD、OOP)
  7. exchange服务器的搭建
  8. 巧妙使用ABBYY FineReader PDF 15页面管理功能调整页面布局
  9. zabbix监控 如何清空历史数据
  10. spring boot项目接入支付宝支付