Ale*_*ork 4 .net garbage-collection
我构建了一个快速程序,需要遍历一个巨大的日志文件(几百万条记录)并从内部找到各种各样的零碎.由于数据量如此巨大,我一直很想看看我的Windows任务管理器性能选项卡,看看有多少CPU和内存被使用.
程序成功获得结果后,CPU使用率明显下降.但是在看到我的内存使用率在执行期间缓慢上升到几千兆字节后,它保持不变.
我试图在我的函数结束时调用GC.Collect(),尝试将事物设置为null,尝试在发布模式下运行程序(我听说GC.Collect()可能无法正常工作,因为我希望它在调试中模式).
如果我关闭程序,内存使用量会下降,但我无法弄清楚为什么在应用程序生命周期内无法清理我的应用程序.在一天结束时,这是一个一次性的应用程序,但我只是想知道我错过了什么,即什么是持有所有这些记忆.
思考?
调用GC.Collect()只是一个收集垃圾的请求,它不是一个订单,所以如果它认为合适,CLR可以选择忽略该请求.
例如,如果有很多垃圾在收集时会导致明显的延迟,但是仍有空闲内存来为后续分配提供服务,那么GC可能会选择忽略您的请求.
许多内存分配器(带或不带垃圾收集)“囤积”他们释放的内存,而不是将其返还给操作系统,这是正常的,因为在许多情况下,刚刚释放的内存将再次被请求,而且速度更快将其保留在进程中,而不是不断将其退回并一次又一次地向操作系统索要它(由于页面对齐问题等原因,将其退回 &c 还需要额外的努力)。
正如您提到的,在一次性应用程序中,这不是问题。当我有一个长时间运行的应用程序,我知道它对大量内存的瞬时需求时,我使用的一种方法是生成一个子进程来执行需要内存的东西,因为当该进程结束时,操作系统将收回记忆。在 Unix 系统(只是 fork)上更容易,但在 Windows 上也不会太糟糕,如果有必要的话。
小智 6
有一种方法.我发现这篇文章,它是西班牙语,确定你理解代码,它的工作原理,我测试了[ http://www.nerdcoder.com/c-net-forzar-liberacion-de-memoria-de-nuestras-aplicaciones/ ] [1]
[DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
private static extern int SetProcessWorkingSetSize(IntPtr process, int minimumWorkingSetSize, int maximumWorkingSetSize);
public static void alzheimer()
{
GC.Collect();
GC.WaitForPendingFinalizers();
SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
}
Run Code Online (Sandbox Code Playgroud)
您的对象可能仍然以某种方式生根.您可以尝试使用内存分析器来查看是否是这种情况.我通常建议使用SciTech的.NET Memory Profiler来做这件事,但Red-Gate也有一个不错的内存分析器.SciTech和Red-Gate都有试用版.使用带有SOS的WinDBG也是可能的.
还有所有的廓有点过时的名单在这里.
当您调用 Collect() 时,不保证垃圾收集器运行。它只是标记要收集的对象。下次 GC 运行时,它将“收集”标记的对象。
.NET 中无法强制 GC 在特定时间点进行收集 - 如果您需要此功能,则需要使用本机代码。