XmlNodeList,我现在才有点明白
随手写了一个小程序,发现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,不怕,看一下索引实现吧:
说不上是它弱还是我弱,反正歪打正着,要不和真不知道效率是差在这个地方。平时用SelectNodes比较多,也从来没有做过这么大一个XmlDocument。
技术还是要靠钻啊。
由于 程序是测试用,所以就随手写了以下代码
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; } |
说不上是它弱还是我弱,反正歪打正着,要不和真不知道效率是差在这个地方。平时用SelectNodes比较多,也从来没有做过这么大一个XmlDocument。
技术还是要靠钻啊。