【问题标题】:GC.Collect() and PerformanceCounterGC.Collect() 和 PerformanceCounter
【发布时间】:2012-05-11 11:21:23
【问题描述】:

我的一位同事确信在 Oracle 的 odp.net ado.net 实现中存在内存泄漏。他编写了一个测试程序来测试这个理论,并在对每个对象调用 dispose 后执行以下操作以确定释放了多少内存:

PerformanceCounter p = new PerformanceCounter("Memory", "Available Bytes");

GC.Collect();
GC.WaitForPendingFinalizers();

float mem = p.NextValue();

然后将得到的性能值与在处理对象之前检索到的值进行比较。这会产生准确的结果吗?

【问题讨论】:

  • 您是否尝试过使用 ProcessExplorer 来监控您的进程中的 .NET 内存和系统内存使用情况?您还没有说明泄漏的是哪种类型的内存...
  • 不,内存管理器不是这样工作的。在完成分配虚拟内存空间的麻烦后,它会将释放的块放回空闲块列表中,以备以后再次使用。
  • 我们不知道是什么类型的内存泄漏,这是测试的一部分原因,以确认有问题。我的问题是确认测试是否有效。
  • 为什么要使用 dispose() 方法?

标签: c# .net memory-leaks odp.net performancecounter


【解决方案1】:

我认为最好的方法是使用GC.GetTotalMemory(true)。您可以在分配对象之前调用它来记录当时分配了多少内存。然后你创建你的对象,也许对它执行一些操作,处理它,确保没有对它的引用(可能只是将局部变量设置为null),然后再次调用它。

请注意返回的值可能不完全准确,根据文档,该方法将返回:

一个数字,它是托管内存中当前分配的字节数的最佳可用近似值。

之后,您可以比较这两个值。如果你反复这样做,你可以看到对象是否真的在泄漏托管内存。

当然,如果对象泄漏非托管内存,这将无济于事。

另一种选择是使用内存分析器,但如果您知道内存可能泄漏的确切位置,这可能会有点过头了。

【讨论】:

  • 感谢您提供有关如何更好地获得结果的想法。这是否意味着我发布的方法有问题?为什么这是一种更好的方法?
  • 是的,您的方法是错误的,请阅读 Hans Passant 的评论。当 CLR 收集垃圾时,它通常不会将内存返回给系统,因此您可能看不到可用字节的任何变化,即使内存实际上已被释放。
猜你喜欢
  • 2012-12-06
  • 2011-12-31
  • 2011-01-15
  • 1970-01-01
  • 1970-01-01
  • 2014-11-28
  • 1970-01-01
  • 2019-10-25
  • 1970-01-01
相关资源
最近更新 更多