大大提高xml读取性能

本文探讨了在处理大型XML文档时,通过改进遍历方式显著提升效率的方法,特别是对比了XmlChildNodes与XPathNodeList在索引实现上的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:http://www.cnblogs.com/beyond914/archive/2005/10/17/256411.html


随手写了一个小程序,发现WebClient返回数据特别慢,不知道是网站的原因还是本身的原因。正好同事也在使用,就手工造了近8W多条数据保存到数据库中,然后用Aspx页面读出,WebClient(WinForm)返回后用XmlDocument读取后显示在窗口中的DataGrid中。测试过程中发现,20多分钟还没有显示出界面。本以为是数据量太大造成数据库读取数据和用WebClient返回有问题,但跟踪一下,返回数据不过十秒,而系统停在了XmlDocument中的节点形成DataTable的地方。

由于 程序是测试用,所以就随手写了以下代码
for( int i = 0; i < root.ChildNodes.Count; i ++ )
{
for( int j = 0; j < root.ChildNodes[i].ChildNodes.Count; j ++ )
{
;数据转换
}
}

发现竟然这个循环就20多分钟还没有完,10秒钟也就循环500多次
引用有问题?修改
int count = root.ChildNodes[0].ChildNodes.Count ;//数量肯定是一致的
for( int i = 0; i < root.ChildNodes.Count; i ++ )
{
XmlNode _node = root.ChildNodes[i] ;
for( int j = 0; j <count; j ++ )
{
;数据转换
}
}
不行,没有用。
把内层循环中的处理去说,保留一个空循环,测试,速度果然提高了不少,10秒钟循环了12000多次。
慢着,怎么会越来越慢?后来连3000次都不到了。难道每次根据节点取索引都从头找吗?
换个思路吧。
int count = root.ChildNodes[0].ChildNodes.Count ;//数据肯定是一致的
XmlNode _node = root.ChildNodes[0] ;
for( int i = 0; i < root.ChildNodes.Count; i ++ )
{
for( int j = 0; j <count; j ++ )
{
;数据转换
}
_node = _node.NextSibling ;
}
再测试,FT,竟然5秒都不到就完成了近8W次的数据转换。
哭笑不得啊!
看了一下定义,XmlNode.ChildNodes的类型为XmlChildNodes,不怕,看一下索引实现吧:public override XmlNode Item(int i)
{
if (i >= 0)
{
XmlNode node1 = this.container.FirstChild;
while (node1 != null)
{
if (i == 0)
{
return node1;
}
node1 = node1.NextSibling;
i--;
}
}
return null;
}


果然啊,XmlChildNodes应该是用链表实现的吧?每次根据索引查找一个节点都要从头遍历一次。好弱。
但是当我们用SelectNodes返回的XmlNodeList的类型却是XPathNodeList,内部数据存储是一个ArrayList,这样看起来索引就要快些了。它的索引返回实现如下

public override XmlNode Item(int index)
{
if (index >= this.list.Count)
{
this.ReadUntil(index);
}
if ((index < this.list.Count) && (index >= 0))
{
return (XmlNode) this.list[index];
}
return null;
}



private ArrayList list;


说不上是它弱还是我弱,反正歪打正着,要不和真不知道效率是差在这个地方。平时用SelectNodes比较多,也从来没有做过这么大一个XmlDocument。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值