从 .NET 文本/闪烁框读取行而不使用太多内存?

Posted

技术标签:

【中文标题】从 .NET 文本/闪烁框读取行而不使用太多内存?【英文标题】:Reading lines from a .NET text/scintilla box without using too much memory? 【发布时间】:2010-06-04 01:35:53 【问题描述】:

我必须创建一个能够很好地处理读取大文件的 C# 程序。

例如,我有一个 60+ mB 的文件。我将所有内容读入一个闪烁框,我们称之为 sci_log。该程序使用大约 200mB 的内存来实现此功能和其他功能。这仍然是可以接受的(并且小于 Notepad++ 用于打开此文件的内存量)。

我还有另一个闪烁盒,sci_splice。用户输入一个搜索词,程序在文件中搜索(如果文件长度足够小,则搜索 sci_log - 没关系,因为它是双向的)以找到 regexp.match。当它找到匹配项时,它将该行与具有先前匹配项的字符串连接起来,并增加一个临时计数变量。当 count 为 100(或 150 或 200,实际上是任何数字)时,我将输出放入 sci_splice,调用 GC.Collect(),然后重复接下来的 100 行(设置 count = 0,将字符串归零)。

我现在没有代码,因为我是用家用笔记本电脑编写的,但问题是它使用了很多内存。 200mB 的内存使用量跃升至 1gB 以上,而且看不到尽头。这仅发生在具有大量正则表达式匹配的搜索中,因此与字符串有关。但问题是,GC 不会释放内存吗?还有,为什么涨这么高?为什么它会超过三倍(最坏的情况)是没有意义的。即使所有 200mB 只是内存中的日志,它所做的只是读取每一行并存储它(最坏的情况)。

经过更多测试后,似乎 Scintilla 在添加行时使用大量内存存在问题。行的初始读取在几分之一秒内具有高达 850mB 的内存峰值。我想我只需要对输出进行分页。

【问题讨论】:

请不要在标题中包含标签(“C#”)。这就是标签的用途。 抱歉,我正要修复它。谢谢。 60MB 不是一个大文件。 2GB 是一个巨大的文件。 当然,但为了举例,我使用了 60mB。 调用 GC.Collect() 是个坏主意。它实际上可以导致对象生命周期被提升... 【参考方案1】:

不要调用 GC.Collect。在这种情况下,我认为这并不重要,因为我认为这个内存最终会出现在大对象堆 (LOH) 上。但关键是.Net 比你更了解内存管理。别管它。

我怀疑您只是按照您描述的方式使用任务管理器来查看它。您至少需要使用 Perfmon。预计您在go here and do pretty much what Tess does 之前没有使用过它,它显示的是获取内存转储。不确定您是否已准备好使用 WinDbg,但这可能是您的下一步。

如果没有看到代码,几乎无法知道它发生了什么。问题也可能在 Scintilla 内部,但我会先检查你在做什么。通过运行 perfmon,您至少可以获得更多信息来确定下一步该做什么。

【讨论】:

【参考方案2】:

如果您使用 System.String 来存储匹配行,我建议您尝试用 System.Text.StringBuilder 替换它,看看这是否有什么不同。

【讨论】:

【参考方案3】:

试试http://msdn.microsoft.com/en-us/library/system.io.memorymappedfiles.memorymappedfile(VS.100).aspx

【讨论】:

以上是关于从 .NET 文本/闪烁框读取行而不使用太多内存?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jquery 从 asp.net 视图模型中动态删除行而不删除集合中的其余下一个对象

从文本文件中读取第一行而不将整个文本文件加载到内存中

文本更改事件期间垂直滚动闪烁文本框

Python Pandas - 编写新的 CSV 标题行而不读取/重写整个文件

如何在索引 2 处向 pandas 数据帧添加额外的行而不覆盖现有索引

在装配中写入行而不返回行的开头(阶梯文本)