【发布时间】:2016-04-11 09:33:47
【问题描述】:
我最近发布了一篇关于由于内存不足错误导致日志文件读取器失败的文章 > Out of memory error archiving a log file
在我有机会尝试更简单的方法(将日志文件命名为带有日期的名称以防止存档)之前,这显然意味着重写方法等,我首先尝试了垃圾收集选项,因为我从来没有使用它,例如 GC.Collect()。
如果在尝试读取日志文件内容时引发内存错误并且它似乎释放了一半的内存,例如在此过程中使用的调试文件(因为日志文件是显然没有行动,所以这是为了帮助我在事后进行调试)我从昨晚的存档过程中得到了这个响应。
Attempt Archive
Take contents of current file with ReadFileString (this is my custom stream reader method I wrote which you can see in the original article)
Taken contents of current file!
In TRY/CATCH - Out of Memory Exception - Try GC.Collect()
Memory used before collection: **498671500**
Memory used after collection: **250841460**
Try again with ReadFileString
How much content have we got? Content Length is **123595955**
We have content from the old log file
所以 GC.Collect 似乎修复了读取文件的问题。
但是我只是想知道,当我调用 GC.Collect() 时,它正在删除 247.83MB 的内存,因为它正在从这个调试中释放出什么样的内存。
因此,我想知道它正在释放什么样的对象或内存,因为我认为 .NET 应该具有良好的内置垃圾收集功能,如果随着时间的推移它会产生这么多“可释放”的内存,我应该定期调用GC.Collect() 每隔一段时间就释放内存或仅仅因为它在第一次尝试将日志文件读入内存时失败而产生的内存量?
显然它已经有一段时间没有处理大文件了,直到我尝试了我以前从未使用过的 GC.Collect,所以我只是想知道内存来自哪里,什么时候正常收集,应该它在别处被调用。
这是一个 Windows 服务应用程序,它嵌入到一个 DLL 中,该 DLL 在一天中使用 JSON 对第 3 方 API 进行多次 HTTP 调用,使用多个计时器来控制它需要运行的每个作业。因此,除非我手动停止服务,否则它会一直运行。
所以我是否应该每晚调用一次 GC.Collect() 就像人们所说的将垃圾收集留给系统的其他文章一样好习惯,但从这个实例来看,它有助于快速解决内存不足的问题抛出错误(我有一台 14GB 64 位计算机正在运行)。
【问题讨论】:
-
它没有解决你的问题,只是推迟了它。就像您可以尝试将项目移植到 x64 一样,这也会延迟问题。您应该避免一次将大文件加载到内存中,这是我想的真正问题。系统无法分配足够的连续内存。
-
在大多数情况下,调用 GC.Collect 会让你更晚受苦,因为 GC 会将所有幸存的对象移至下一代,因此它们的寿命会更长!
-
您可能有一堆小对象不足以强制进行 gen#2 集合。其中引用了大对象堆中的一个大块。 GC.Collect() 可以释放四分之一 jiggabyte 的那种场景。如果 GC 的行为不“自然”,那么必须提供帮助并没有错。请记住,永远不需要使用 LOH 来归档日志文件,当您一次复制一行而不是使用 File.ReadAllText() 之类的东西时,它也同样有效。减去这种故障模式。
-
您的内存问题只是您的实际问题的症状:将整个文件读入内存。对于您要解决的特定问题,只需考虑重命名(使用 File.Move)文件(或复制使用 File.Copy 的文件)。这样您就可以完全避免内存问题。
标签: c# .net io garbage-collection readfile