灵感之源在屡次声明时间太紧,没法更新博客,可依然还是抽空更新,学习的榜样。
相比,太是惭愧。要是如此下去,我的BlogReader也就无疾而终了。
所以这两天,少玩一下,做了一些更新。
原来版本的BlogReader采用启动的时候,将文章全部读入的方式,类似于SharpReader(当时就是抄他的)。
可是随着文章数量的增加,内存也同比增加。前几天,我的文章项有8500篇,光启动内存就到了60M。然后浏览更新操作一段时间,很快就能到80M,有时候离谱的到过一百兆。
于是决定改。首先想到的就是随用随取,换Channel就释放前面的Channel资源。想法挺好,现实却打击不小。随用随取,没问题,可是在释放资源的时候,确是用10减5,内存还是不停增加。分析原因有二:1、自身的代码不完善,资源申请了却没有很好得归还代码;二、Net在处理频繁的新建、删除对象时,垃圾收集并不能做的及时,而是有迟后。这仅是个人观点,希望大家交流。
在上一种情况下内存使用没有太多改善,宣告暂时此路不通。
然后想到是,是否可以部分载入?分析了一下博客站点,发现一个特点,标题是最经常看的,而内容往往感兴趣的才看。
于是想了一条比较好实现的途径,在原来大框架不变的情况下,将文章的内容单独存到可随机访问的流文件中,在Channel文件中维护一个链接列表。又考虑到文章项后经常加入删除,不可能采用添加就附到文件尾部做法。于是将流文件分块,每块大小1024字节,内容的原始大小小于1024,直接存盘,否则压缩再存盘。删除操作则将归还的块的位置在链接列表复位。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
和Pos4。Pos3是当前的第一处空白块,指向下一个空白块。而Pos5则指向的是一个当前没有分配的空间。当Pos5使用,就分配后续的空间Pos6,否则维持文件大小不变。删除操作,修改原文件占用的最有一个快的指针,将其指向第一空白块,而第一空白块指针则指向删除文件的第一文件块。
{
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 * 1024, 1024);
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)
{
}
}
}
{
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 * 1024, 1024);
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 "";
}
也希望在Net下内存使用经验丰富的各位,给与指导。
当然既然使用了压缩,那么在异步取网页的时候,也加入了支持gzip、deflate格式的能力。感觉在收取向博客园这样更新文件较大的博客网站时,帮助很大。
先写到这,由于代码还在改写中,所以这次没有上传。同上次一样,在Net2.0的环境下修改,所以也没有Net1.1 的文件。准备在两者同步的情况下,同时上传。