为什么调用GC.Collect正在加快速度

时间:2012-09-20 05:49:52

标签: c++ .net garbage-collection swig dispose

我们有一个C ++库(No MFC,No ATL),它为我们的.NET应用程序提供了一些核心功能。 SWIG使用C ++ DLL生成可用于使用PInvoke访问其类/方法的C#程序集。在我们的.NET应用程序中使用此C#程序集来使用C ++ DLL中的功能。

问题与内存泄漏有关。在我们的.NET应用程序中,我的.NET代码中有一个循环,它从C ++ DLL创建了数千个特定类的实例。循环在创建实例时保持减速但如果我在循环内调用GC.Collect()(我不知道这是不推荐的),则处理变得更快。为什么是这样?在类型上调用Dispose()对速度没有任何影响。我期待使用GC.Collect()时程序速度的降低,但恰恰相反。

SWIG生成的每个类都有一个调用Dispose()的析构函数。每个Dispose方法都有一个锁(this)围绕调用处理非托管内存的语句。最后它调用GC.SuppressFinalize。我们还在Release版本中偶尔看到AccessViolationException。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

某些类型的物品可以自行清理(通过Finalize),如果它们在没有被处理的情况下被抛弃,但在终结器到达它们之前可能需要花费很多钱; Framework中的一个示例是Microsoft.VisualBasic.Collection.GetEnumerator()返回的枚举器。每次调用GetEnumerator()都会将新枚举器对象包装的对象附加到由集合管理的各种私有更新事件中“当枚举器为Dispose时,它将取消订阅其事件。如果GetEnumerator()被多次调用(例如数千或数百万)而没有调查员被处理并且没有干预垃圾收集,那么集合将变得越来越慢(比正常情况慢几百或几千倍)作为事件订阅名单不断增长。然而,一旦发生垃圾收集,任何被放弃的枚举器'Finalize方法都会清理他们的订阅,并且事情将再次开始正常工作。

我知道你已经说过你正在调用Dispose,但是我怀疑是什么东西正在创建一个IDisposable对象实例而不是在它上面调用Dispose。如果IDisposableFoo创建并拥有IDisposableBar的实例,但Foo不会Dispose该实例位于其Dispose内{1}}实施,在Dispose的实例上调用Foo将无法清除Bar。一旦Foo的实例被放弃,无论是Dispose d,它的Bar最终会被放弃而不会被丢弃。

答案 1 :(得分:0)

你在Dispose方法中调用GC.SupressFinalize吗?无论如何,有一篇很好的MSDN文章解释了如何编写GC友好代码 - garbage collection basics and performance hints。也许它会有用。