继续:.NET CF下面“大”规模数据的读取和保存

上一个Post讲到,在.NET CF下面直接用XmlDocument来读取比较大的Xml文件是非常缓慢的,但是我们也只是知道了一个绝对值,没有参照物,还是不知道到底怎么样。其实利用上一个Post的代码,读取同样格式和内容的Xml文件,当Item数量在接近6000的时候,仅仅是遍历一次所有的内容,仍然将会花费 50秒左右的时间。注意这里仅仅是遍历,没有其他多余的语句,例如将数据用某种类型结构保存在内存当中等等。当然,这比197秒要好多了,但是这仍然不能够满足我们的需求。在跟进一步的提高速度之前,还是先尝试粗略分析一下性能的瓶颈在哪里。

用Reflector分析一下Xml相关的各个类,我们会发现XmlDocument实际上是利用XmlReader来解析Xml文件的,同时还会同时构造每一个节点,比如XmlElement或者XmlAttribute。很明显XmlDocument肯定不会比XmlReader更加有效率,至少XmlDocument还需要构造一系列的对象,并且还是递归的。如果我们能够减少节点的层次,或者尽量封闭节点(使之不具备拥有子节点的资格,例如把XmlElement的数据挪到XmlAttribute里面),那么XmlDocument的效率会有一定层次的提高。如果说数据量不是非常大(大概100左右),不希望用复杂的方式来完成本来应该很简单的事情,那么这个方法也值得尝试。
None.gif < Root >
None.gif  
< Item  id  = "1"  name  = "hello"  something  = "xxx"  extension  = "yyy"  abc  = "efg" > Text </ Item >
None.gif  
< Item  id  = "2"  name  = "world"  something  = "zzz"  type  = "reference"  extension  = "123" > China </ Item >
None.gif  ……
None.gif
</ Root >
不过我们也可以预见这个提高的程度是相当有限的,甚至不如分割文件所带来的效率。除了可能不雅观这个不充足的理由之外,如果我们需要对something用一个Attribute来额外描述的时候,这个方法就部分的失效了。当我看了一遍Xml里面的相关代码后,并没有完全搞清楚里面的机制,但是有一点是肯定的——代码复杂,从XmlDocument到XmlReader都是复杂的代码,几乎没有一目了然的东西。不过在这个复杂的背后,其实有着一定的效率优化,这在后面的实验结果里面可以看出来,但是我却暂时无法从.NET CF里面的代码直接分析出来,到底是哪个部分的性能优化带来了这些性能提升。

有的时候我们也需不愿意,或者无法进行文件分割,比如说所有的数据都必须要加载了才能够计算,又或者我们不能够冒分割文件所带来的一些技术风险,那么也许我们需要考虑用自己的文件格式来保存了,比如说二进制(也许文本方式也是一个不错的选择,我说的是纯文本)。如果您同意了我这个假设成立,那么我们可以开始着手研究一下有关文件读取方面的问题。不要以为这是一个简单的问题,我之前也以为这是一个很简单的问题,而最后我却发现这个问题要看硬件平台如何。我一年前在PC上面做应用,感觉文件读取和内存读取效率相差不大。当时我就猜测由于PDA的文件在内存当中,因此不会像桌面PC一样,文件的读取效率和内存的读取效率相差上千倍,顶多相差十倍。而当时的工作经验告诉我似乎结果就是这样的,因为我在PDA上面读取文件几乎就没有遇到什么性能瓶颈。然而这一次在SmartPhone上面的情况却完全不一样,让我大吃一惊。如果有机会大家可以在SmartPhone上面运行一下如下的代码片断,保证有一个深刻的体会:

None.gif          void  Test()
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
// Create an 1MB file for testing, make the buffer size of filestream object to 640k
InBlock.gif
            FileStream fs = new FileStream(
InBlock.gif                
"Test.Binary",
InBlock.gif                FileMode.Create,
InBlock.gif                FileAccess.ReadWrite,
InBlock.gif                FileShare.None,
InBlock.gif                
655360
InBlock.gif                );
InBlock.gif            
byte[] buff = new byte[1048576];
InBlock.gif            fs.Write(buff, 
0, buff.Length);
InBlock.gif
InBlock.gif            
long ticks;
InBlock.gif
InBlock.gif            
// Reset the position
InBlock.gif
            fs.Position = 0;
InBlock.gif            BinaryReader br 
= new BinaryReader(fs);
InBlock.gif            
// Test reading every byte from BinaryReader using for statement:
InBlock.gif
            ticks = DateTime.Now.Ticks;
InBlock.gif            
for(i = 0; i < buff.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                br.ReadByte();
ExpandedSubBlockEnd.gif            }

InBlock.gif            ticks 
= DateTime.Now.Ticks - ticks;
InBlock.gif            MessageBox.Show(ticks.ToString());
InBlock.gif
InBlock.gif            
// Reset the position and test reading every byte using while statement:
InBlock.gif
            fs.Position = 0;
InBlock.gif            ticks 
= DateTime.Now.Ticks;
InBlock.gif            
while (fs.Position != fs.Length)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                br.ReadByte();
ExpandedSubBlockEnd.gif            }

InBlock.gif            ticks 
= DateTime.Now.Ticks - ticks;
InBlock.gif            MessageBox.Show(ticks.ToString());
InBlock.gif
InBlock.gif            
// Reset the position and test reading via MemoryStream
InBlock.gif            
// using while statement:
InBlock.gif
            fs.Position = 0;
InBlock.gif            ticks 
= DateTime.Now.Ticks;
InBlock.gif            
// we define another buffer to test mem alloc time all together
InBlock.gif
            byte[] buffRead = new byte[buff.Length];
InBlock.gif            fs.Read(buffRead, 
0, buffRead.Length);
InBlock.gif            MemoryStream ms 
= new MemoryStream(buffRead);
InBlock.gif            br 
= new BinaryReader(ms);
InBlock.gif            
while (ms.Position != ms.Length)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                br.ReadByte();
ExpandedSubBlockEnd.gif            }

InBlock.gif            ticks 
= DateTime.Now.Ticks - ticks;
InBlock.gif            MessageBox.Show(ticks.ToString());
InBlock.gif            
InBlock.gif
InBlock.gif            fs.Close();
InBlock.gif            
ExpandedBlockEnd.gif        }

None.gif

待续……
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值