我面临的情况是,我必须一次创建数千个对象,实例化对象和垃圾收集它们的成本正在影响应用程序的性能,并且垃圾收集器运行的影响会造成伤害性能更高,因为这是在较旧的硬件上,所以我主要是试图防止产生垃圾。我相信内存池可以解决我的问题,但我不确定内存池如何知道池中的资源何时被释放以供重用。棘手的部分是池中对象的接收者最终会在整个程序中传递该对象,并且很难知道何时可以手动释放它。我希望它像一个 WeakReference
,在那里我可以知道什么时候没有人再使用它。但我的理解是,如果我在内存池中使用 WeakReference
,那么它最终会从池本身收集垃圾,我需要这些对象几乎永远保留,以便它们继续被回收。有时程序可以在不需要这些对象的情况下运行一段时间,所以我想垃圾收集器会在下一次需要它们之前收集它们,然后随着另外一千个这些对象的产生而触发另一次性能损失。
有没有一种方法可以确保永远不会收集这些对象,但知道什么时候除了内存池本身之外没有对它们的引用?我是否需要以某种方式为这些对象实现引用计数?
我已经在谷歌上搜索了几个小时,但没有看到任何内存池的实现都不需要用户让内存池知道他们何时使用它。我很难相信在 C# 中无法做到这一点。
最佳答案
Is there a way I can make sure these objects are never collected, but know when there are no references to them aside from the memory pool itself?
通常一个对象池只保存对可用对象的引用(你可以查看 ObjectPool
implementation in Roslyn )。考虑到这一点,您可以使用终结器来复活对象,并在对象无法访问时将其返回到池中。
但是,我认为它不会提高性能。整个池很快就会达到第 2 代,因此无法访问的对象将需要进行完整的垃圾回收才能返回到池中。根据程序中的内存使用模式,它可能不会经常发生。您当然可以使用 GC.Collect()
和 GC.WaitForPendingFinalizers()
,但这也会损害性能。您可以尝试一下,看看是否有帮助。
另一个问题是设计 - 您的对象与池耦合。
我宁愿尝试明确地将对象返回到池中。请记住,并非所有对象都必须返回。如果没有更多可用对象,池可以创建新对象。那些没有被归还的只会被垃圾收集。检查是否有一些您确定不再需要对象的代码路径。如果找不到,请尝试重构代码。
关于C# .NET 3.5 : Memory Pool, 知道对象何时被释放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33378138/