为什么要打电话给GC.收集正在加快速度

Why calling GC.Collect is speeding things up

本文关键字:速度 打电话 GC 为什么      更新时间:2023-10-16

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

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

SWIG 生成的每个类都有一个调用 Dispose() 的 ~析构函数。每个 Dispose 方法在调用以释放非托管内存的语句周围都有一个锁 (this)。最后它调用 GC。抑制完成。我们还在发布版本中偶尔看到 AccessViolationException。任何帮助将不胜感激。

某些类型的对象可以在自己之后清理(通过Finalize),如果它们被放弃而不被处置,但在终结器处理它们之前保留它们的成本可能很高; 框架中的一个例子是Microsoft.VisualBasic.Collection.GetEnumerator()返回的枚举器。 每次调用GetEnumerator()都会将新枚举器对象包装的对象附加到集合管理的各种私有更新事件中,当枚举器Disposed 时,它将取消订阅其事件。 如果在没有释放枚举器且没有干预垃圾回收的情况下多次调用GetEnumerator()(例如数千或数百万次),则随着事件订阅列表的不断增长,收集将变得越来越慢(比正常情况慢数百或数千倍)。 但是,一旦发生垃圾收集,任何被遗弃的枚举器的Finalize方法都将清理其订阅,并且事情将再次开始正常运行。

我知道你说过你正在调用Dispose,但我怀疑某些东西正在创建一个IDisposable对象实例而不是在其上调用Dispose。 如果类Foo创建并拥有IDisposableBar的实例,IDisposableFoo不会在其自己的Dispose实现中Dispose该实例,则在Foo实例上调用Dispose不会清理Bar。 一旦Foo实例被放弃,无论它是否被Disposed,其Bar最终都会被放弃而不被处置。

你叫GC吗?压制在您的处置方法中完成?无论如何,有很好的MSDN文章解释了如何编写GC友好代码 - 垃圾回收基础知识和性能提示。也许它会有用。