在运行我的.net进程很长一段时间后,我发现GC知道的内存与进程工作集之间存在很大差异。
我正在监控的值是GC.GetTotalMemory(false)和Process.WorkingSet。
如果我签入“任务管理器”(或使用SysInternals工具),WorkingSet(Process)的值和“任务管理器”中显示的值不匹配,但它们不知何故接近(比方说,100mb)在任务管理器中,130在WorkingSet中),但让我感到震惊的是GC.GetTotalMemory(false)就像是40M左右。
我已经通过探查器运行了几次(我最喜欢的是ants memory profiler from redgate),并且很容易检查是否有一个名为“空闲记忆”的值,这通常是GC“看到”和操作系统看到的内容(好的,加上加载的DLL等)。
几个问题:
有没有办法以编程方式监控这个“GC空闲内存”。是的,我可以使用分析器,但在长时间运行的过程中并不那么容易。
如果你的进程运行了很长时间,分配了大量内存然后释放它(并且分配意味着数千或数百万个对象,不像大分配和免费那么简单),问题在于它尽管GC值低且正确,但永远不会“缩小”到低值。有没有办法来解决这个问题?可能是因为我的流程出现了问题,但多年来它已被多次描述,而且似乎没有泄漏。
谢谢
答案 0 :(得分:0)
只是要复活一个古老的线程,如果要监视"GC free memory"
,可以定期调用GC.GetTotalMemory(false)
并存储值。将其转储到磁盘或数据库之类的东西。另外,您可以使用prometheus-net
(https://github.com/prometheus-net/)之类的库,该库将为您导出此索引和大量指标。
关于第二个问题,有一种强制您的应用程序缩小的方法,但它不是dot net native,它仅是Windows,建议不:
[DllImport("psapi.dll")]
static extern int EmptyWorkingSet(IntPtr hwProc);
static void MinimizeFootprint()
{
EmptyWorkingSet(Process.GetCurrentProcess().Handle);
}
据我所知,我认为如果服务器承受内存压力,操作系统将解决此问题,并且如果内存仍分配给您的进程,则对于您的应用程序和整个服务器而言,效率更高。这是因为将来很有可能再次需要它,因此,当它仅需再次分配时,尤其是在服务器具有足够的内存时,就没有必要清理它。