懒惰的笨鸟

学习再学习,一切都是为学习。 交流再交流,交流好了再学习。

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

灵感之源在屡次声明时间太紧,没法更新博客,可依然还是抽空更新,学习的榜样。
相比,太是惭愧。要是如此下去,我的BlogReader也就无疾而终了。
所以这两天,少玩一下,做了一些更新。

原来版本的BlogReader采用启动的时候,将文章全部读入的方式,类似于SharpReader(当时就是抄他的)。
可是随着文章数量的增加,内存也同比增加。前几天,我的文章项有8500篇,光启动内存就到了60M。然后浏览更新操作一段时间,很快就能到80M,有时候离谱的到过一百兆。
于是决定改。首先想到的就是随用随取,换Channel就释放前面的Channel资源。想法挺好,现实却打击不小。随用随取,没问题,可是在释放资源的时候,确是用10减5,内存还是不停增加。分析原因有二:1、自身的代码不完善,资源申请了却没有很好得归还代码;二、Net在处理频繁的新建、删除对象时,垃圾收集并不能做的及时,而是有迟后。这仅是个人观点,希望大家交流。

在上一种情况下内存使用没有太多改善,宣告暂时此路不通。
然后想到是,是否可以部分载入?分析了一下博客站点,发现一个特点,标题是最经常看的,而内容往往感兴趣的才看。
于是想了一条比较好实现的途径,在原来大框架不变的情况下,将文章的内容单独存到可随机访问的流文件中,在Channel文件中维护一个链接列表。又考虑到文章项后经常加入删除,不可能采用添加就附到文件尾部做法。于是将流文件分块,每块大小1024字节,内容的原始大小小于1024,直接存盘,否则压缩再存盘。删除操作则将归还的块的位置在链接列表复位。

 Pos0

End 

 Pos1

 Pos2

 Pos2

 Pos4

 Pos3

 Pos5

 Pos4

 End

 Pos5

Pos6 

 

 

上面的示意图就是在某一情况下的链表,Pos0有一文件,小于1024。Pos1处有一文件,占用了3块空间,Pos1、Pos2
和Pos4。Pos3是当前的第一处空白块,指向下一个空白块。而Pos5则指向的是一个当前没有分配的空间。当Pos5使用,就分配后续的空间Pos6,否则维持文件大小不变。删除操作,修改原文件占用的最有一个快的指针,将其指向第一空白块,而第一空白块指针则指向删除文件的第一文件块。

        public void SaveDes()
        
{
            
if (this.IsSaved == false && this.Description.Length > 0)
            
{
                Encoding e 
= Encoding.Default;
                
byte[] desBytes = e.GetBytes(Description);

                _DesLength 
= desBytes.Length;
                _DesZipedLength 
= _DesLength;

                
byte[] bytes = null;
                
if (_DesLength > 1024)
                
{
                    Deflater dr 
= new Deflater(Deflater.DEFAULT_COMPRESSION, true);
                    dr.SetInput(desBytes);
                    dr.Flush();
                    bytes 
= new byte[desBytes.Length];

                    dr.Deflate(bytes);
                    _DesZipedLength 
= (int)dr.TotalOut;
                }

                
else
                    bytes 
= desBytes;

                _StartPos 
= _Channel.FirstEmptyPos;
                
int FirstEmptyPos = _StartPos;

                
try
                
{
                    Stream desStream 
= _Channel.desStream;
                    
if(desStream == null)
                        desStream 
= File.Open(_Channel.Feed.desFileName, FileMode.Open);

                    desStream.Position 
= FirstEmptyPos * 1024;

                    
int blockCount = _DesZipedLength / 1024;
                    
int currentBlock = 0;
                    
for (; currentBlock < blockCount; currentBlock++)
                    
{
                        desStream.Write(bytes, currentBlock 
* 10241024);

                        FirstEmptyPos 
= _Channel.StoreTable[FirstEmptyPos];
                        
if (_Channel.StoreTable.Count == FirstEmptyPos)
                        
{
                            _Channel.StoreTable.Add(_Channel.StoreTable.Count 
+ 1);
                        }

                    }

                    desStream.Write(bytes, currentBlock 
* 1024, _DesZipedLength - currentBlock * 1024);
                    desStream.Flush();

                    
int endPos = FirstEmptyPos;
                    FirstEmptyPos 
= _Channel.StoreTable[FirstEmptyPos];
                    _Channel.StoreTable[endPos] 
= -1;
                    _Channel.FirstEmptyPos 
= FirstEmptyPos;

                    
if (_Channel.StoreTable.Count == FirstEmptyPos)
                    
{
                        _Channel.StoreTable.Add(_Channel.StoreTable.Count 
+ 1);
                    }

                    _Description 
= "H";
                    _IsSaved 
= true;
                }

                
catch(Exception ex)
                
{
                }

            }

        }


        public string LoadDes()
        
{
            Stream desStream 
= null;
            
byte[] readbytes = new byte[_DesZipedLength];
            
try
            
{
                
if (desStream == null || desStream.CanRead == false)
                    desStream 
= File.Open(_Channel.Feed.desFileName, FileMode.Open);

                
int blockCount = _DesZipedLength / 1024;

                
int nextPos = _StartPos;
                desStream.Position 
= nextPos * 1024;

                
int currentBlock = 0;
                
for (; currentBlock < blockCount; currentBlock++)
                
{
                    desStream.Position 
= nextPos * 1024;
                    desStream.Read(readbytes, currentBlock 
* 10241024);
                    nextPos 
= _Channel.StoreTable[nextPos];
                }

                desStream.Read(readbytes, currentBlock 
* 1024, _DesZipedLength - currentBlock * 1024);

                
byte[] unzipBytes;

                
if (_DesLength > 1024)
                
{
                    Inflater ir 
= new Inflater(true);
                    ir.SetInput(readbytes);
                    unzipBytes 
= new byte[_DesLength];
                    ir.Inflate(unzipBytes);
                }

                
else
                    unzipBytes 
= readbytes;

                Encoding reade 
= Encoding.Default;
                
return reade.GetString(unzipBytes);
            }

            
catch
            
{
            }

            
finally
            
{
                
if (desStream != null)
                    desStream.Close();
            }

            
return "";
        }
在这样修改后,内存使用感觉改变还是比较明显的。通过Windows的性能监视,内存下降三分之一还强。而且长期运行优势更明显。
也希望在Net下内存使用经验丰富的各位,给与指导。
当然既然使用了压缩,那么在异步取网页的时候,也加入了支持gzip、deflate格式的能力。感觉在收取向博客园这样更新文件较大的博客网站时,帮助很大。
先写到这,由于代码还在改写中,所以这次没有上传。同上次一样,在Net2.0的环境下修改,所以也没有Net1.1 的文件。准备在两者同步的情况下,同时上传。
posted on 2004-12-29 21:11  loli  阅读(1266)  评论(4编辑  收藏  举报