Dan*_*tti 7 .net c# io memory-leaks
Edit2:我只是想确定我的问题是清楚的:为什么,在AppendToLog()的每次迭代中,应用程序使用15mb以上?(原始日志文件的大小)
我有一个名为AppendToLog()的函数,它接收HTML文档的文件路径,进行一些解析并将其附加到文件中.它以这种方式调用:
this.user_email = uemail;
string wanted_user = wemail;
string[] logPaths;
logPaths = this.getLogPaths(wanted_user);
foreach (string path in logPaths)
{
this.AppendToLog(path);
}
Run Code Online (Sandbox Code Playgroud)
在每次迭代中,RAM使用量增加15mb左右.这是功能:(看起来很长但很简单)
public void AppendToLog(string path)
{
Encoding enc = Encoding.GetEncoding("ISO-8859-2");
StringBuilder fb = new StringBuilder();
FileStream sourcef;
string[] messages;
try
{
sourcef = new FileStream(path, FileMode.Open);
}
catch (IOException)
{
throw new IOException("The chat log is in use by another process."); ;
}
using (StreamReader sreader = new StreamReader(sourcef, enc))
{
string file_buffer;
while ((file_buffer = sreader.ReadLine()) != null)
{
fb.Append(file_buffer);
}
}
//Array of each line's content
messages = parseMessages(fb.ToString());
fb = null;
string destFileName = String.Format("{0}_log.txt",System.IO.Path.GetFileNameWithoutExtension(path));
FileStream destf = new FileStream(destFileName, FileMode.Append);
using (StreamWriter swriter = new StreamWriter(destf, enc))
{
foreach (string message in messages)
{
if (message != null)
{
swriter.WriteLine(message);
}
}
}
messages = null;
sourcef.Dispose();
destf.Dispose();
sourcef = null;
destf = null;
}
Run Code Online (Sandbox Code Playgroud)
我已经有了这个日子,我不知道该做什么:(
编辑:这是ParseMessages,这是一个使用HtmlAgilityPack去除HTML日志部分的函数.
public string[] parseMessages(string what)
{
StringBuilder sb = new StringBuilder();
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(what);
HtmlNodeCollection messageGroups = doc.DocumentNode.SelectNodes("//body/div[@class='mplsession']");
int messageCount = doc.DocumentNode.SelectNodes("//tbody/tr").Count;
doc = null;
string[] buffer = new string[messageCount];
int i = 0;
foreach (HtmlNode sessiongroup in messageGroups)
{
HtmlNode tablegroup = sessiongroup.SelectSingleNode("table/tbody");
string sessiontime = sessiongroup.Attributes["id"].Value;
HtmlNodeCollection messages = tablegroup.SelectNodes("tr");
if (messages != null)
{
foreach (HtmlNode htmlNode in messages)
{
sb.Append(
ParseMessageDate(
sessiontime,
htmlNode.ChildNodes[0].ChildNodes[0].InnerText
)
); //Date
sb.Append(" ");
try
{
foreach (HtmlTextNode node in htmlNode.ChildNodes[0].SelectNodes("text()"))
{
sb.Append(node.Text.Trim()); //Name
}
}
catch (NullReferenceException)
{
/*
* We ignore this exception, it just means there's extra text
* and that means that it's not a normal message
* but a system message instead
* (i.e. "John logged off")
* Therefore we add the "::" mark for future organizing
*/
sb.Append("::");
}
sb.Append(" ");
string message = htmlNode.ChildNodes[1].InnerHtml;
message = message.Replace(""", "'");
message = message.Replace(" ", " ");
message = RemoveMedia(message);
sb.Append(message); //Message
buffer[i] = sb.ToString();
sb = new StringBuilder();
i++;
}
}
}
messageGroups = null;
what = null;
return buffer;
}
Run Code Online (Sandbox Code Playgroud)
正如许多人所提到的,这可能只是GC的一个工件,没有像你期望的那样快速清理内存存储.对于托管语言,例如C#,Java等,这是正常的.如果您对该用法感兴趣,您确实需要查明分配给您的程序的内存是否可用.与此相关的问题是:
您的代码看起来不会有"内存泄漏".在托管语言中,您实际上不会像在C/C++中那样出现内存泄漏(除非您使用的是不安全的C/C++外部库).但是,您确实需要注意保留或隐藏的引用(如已被告知删除项目但未设置内部数组元素的Collection类null).通常,除非将对象的引用存储到对象/类变量中,否则对堆栈引用的对象(本地和参数)不能"泄漏".
您对代码的一些评论:
您可以通过预先分配StringBuilder至少适当的大小来减少内存的分配/释放.因为你知道你需要将整个文件保存在内存中,所以将它分配给文件大小(这实际上会给你一个比你需要的大一点的缓冲区,因为你没有存储换行字符序列,但文件可能是有他们):
FileInfo fi = new FileInfo(path);
StringBuilder fb = new StringBuilder((int) fi.Length);
Run Code Online (Sandbox Code Playgroud)
您可能希望确保文件在获取其长度之前存在,fi用于检查该文件.请注意,int根据您的问题文本,我只是将长度向下转换为无错误检查,因为您的文件小于2GB.如果不是这种情况,那么你应该在投射之前验证长度,如果文件太大,可能会抛出异常.
我建议删除variable = null代码中的所有语句.这些不是必需的,因为它们是堆栈分配的变量.同样,在这种情况下,它不会帮助GC,因为该方法将不会存在很长时间.因此,通过让它们在代码中创建额外的混乱并且更难以理解.
在您的ParseMessages方法中,您捕获NullReferenceException并假设它只是一个非文本节点.这可能会导致将来出现混乱的问题.由于数据中可能存在的某些内容通常会发生这种情况,因此您应检查代码中的条件,例如:
if (node.Text != null)
sb.Append(node.Text.Trim()); //Name
Run Code Online (Sandbox Code Playgroud)
例外情况是代码中的异常/意外情况.将重要意义分配给NullReferenceException存在空引用可能(可能会)try现在或将来的更改中隐藏同一块的其他部分中的错误.
| 归档时间: |
|
| 查看次数: |
6047 次 |
| 最近记录: |