【问题标题】:How to solve memory leak caused by System.Diagnostics.PerformanceCounter如何解决 System.Diagnostics.PerformanceCounter 引起的内存泄漏
【发布时间】:2010-07-16 16:04:38
【问题描述】:

总结

我编写了一个以参数为参数的进程监视器命令行应用程序:

  • 进程名称或进程 ID
  • CPU 阈值百分比。

程序所做的是监视所有具有传递的名称或 pid 的进程,如果它们的 CPU 使用率超过阈值%,它会杀死它们。

我有两个课程: ProcessMonitorProcessMonitorList

前者,环绕System.Diagnostics.PerformanceCounter
后者是一个IEnumarable,它允许前者的类似列表的结构。

问题

程序本身运行良好,但是如果我在任务管理器上查看内存使用情况,它会以每秒约 20kB 的增量增长。注意:程序每秒通过PerformanceCounter轮询CPU计数器。

这个程序需要在一个使用率很高的服务器上运行,并且它正在监视大量的进程。 (20-30)。

调查至今

我使用 PerfMon 监控进程的 私有字节所有堆中的总字节数,并根据下面引用的文章中介绍的逻辑,我的结果表明,在波动时,该值仍然在可接受的范围内,因此没有内存泄漏:
Article

我还使用 FxCop 分析了我的代码,但它没有提出任何相关的内容。

情节变厚

不习惯只是说,​​哦,那么没有内存泄漏,我进一步调查,发现(通过调试)以下代码行用箭头显示了泄漏发生的位置显示确切的行。

_pc = new PerformanceCounter("Process", "% Processor Time", processName);

上面是 _pc 被初始化的地方,在我的ProcessMonitor类的构造函数中。

以下是导致内存泄漏的方法。每秒都会从我的 main 调用此方法。

public float NextValue()
{
        if (HasExited()) return PROCESS_ENDED;
        if (_pc != null)
        {
            _lastSample = _pc.NextValue();   //<-----------------------
            return _lastSample;
        }
        else return -1;
}

这表明泄漏存在于 System.Diagnostics.PerformanceCounter 类中的NextValue() 方法中。

我的问题:

  1. 这是一个已知问题,我该如何解决?
  2. 我认为任务管理器的内存使用量增加意味着确实存在内存泄漏的假设是否正确?
  3. 是否有更好的方法来监控特定进程的多个实例并在它们超过特定的 CPU 使用率阈值时将其关闭,然后发送电子邮件?

【问题讨论】:

  • 如果你运行你的程序一段时间,增加会继续吗?说 5、10、20 分钟?
  • 是的,它继续增加,并且变得非常大。我会在 5 分钟内收集一些统计数据并发布。
  • 从我收集的统计数据看来,它正在增长到大约 5k,然后下降到 4k,然后增长到 5k 等,并继续这种行为(可接受),所以我不认为这不再是一个问题

标签: memory-leaks system.diagnostics


【解决方案1】:

所以我想我想通了。
使用Reflector 工具,我能够检查System.Diagnostics 中的代码。

看来NextValue方法调用

GC.SuppressFinalization();

这意味着(我认为,如果我错了,请纠正)我需要在我的所有课程中明确调用 Dispose()

所以,我所做的是在我的所有类上实现IDisposable,尤其是围绕PerformanceCounter 的类。

我更明确地清理了我的IList&lt;PerformanceMonitor&gt; 和内部结构, 瞧,记忆行为改变了。

它会振荡,但内存使用量在很长一段时间内明显介于可接受的范围之间。

【讨论】:

  • 你是对的,PerformanceCounter 实现了 IDisposable。您需要调用 Close,将 counter 变量包装在 using 语句中或调用 Dispose 以释放共享资源。见:msdn.microsoft.com/en-us/library/…
  • 在使用 PerformanceCounterCategory 并调用 GetCounters() 时也要小心。它返回一个 PerformanceCounter 对象列表,您也必须处理所有这些对象。
猜你喜欢
  • 2015-06-28
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
  • 2018-04-11
  • 2020-04-07
  • 1970-01-01
相关资源
最近更新 更多