6

何时使用 C# 进行对象池?任何好的前...

维护一个经常使用的对象池并从池中获取一个而不是创建一个新对象的优点和缺点是什么?

4

5 回答 5

5

我会将内存碎片添加到列表中。当使用封装本机资源的对象时,可能会发生这种情况,这些资源在分配后无法被垃圾收集器移动,并且可能会导致堆碎片化。

一个真实的例子是当您创建和销毁大量套接字时。它们用于读取/写入数据的缓冲区必须固定才能传输到本机 WinSock API,这意味着当垃圾收集发生时,即使为被破坏的套接字回收了一些内存 - 它也可能会离开内存处于碎片状态,因为 GC 在收集后无法压缩堆。因此,读/写缓冲区是池化的主要候选者。此外,如果您使用的是 SocketEventArgs 对象,那么这些对象也是不错的选择。

这是一篇很好的文章,它讨论了垃圾收集过程、内存压缩以及为什么对象池有帮助。

于 2010-04-15T14:57:10.100 回答
5

我能想到的通常池化的资源只有两种类型:线程和连接(即到数据库)。

两者都有一个首要问题:稀缺性。

  • 如果你创建了太多线程,上下文切换会浪费你所有的 CPU 时间。
  • 如果您创建了太多的网络连接,那么维护这些连接的开销就会变得比连接应该做的任何事情都多。
  • 此外,对于数据库,由于许可原因,连接数可能会受到限制。

因此,您想要创建资源池的主要原因是您是否只能在任何时候都只能拥有有限数量的资源池。

于 2010-04-15T15:07:46.007 回答
4
  1. 当对象创建代价高昂时
  2. 当您可能会遇到内存压力时 - 对象太多(例如 - 享元模式)
于 2010-04-15T14:55:07.123 回答
1

对于游戏,GC 可能会在某些情况下引入不必要的延迟。如果是这种情况,重用对象可能是一个好主意。在这个线程中有一些关于这个主题的有用的考虑。

于 2010-12-28T16:21:27.967 回答
0

有一篇出色的 MSDN 杂志文章,名为 Rediscover the Lost Art of Memory Optimization in Your Managed Code by Erik Brown http://msdn.microsoft.com/en-us/magazine/cc163856.aspx. 它包括一个带有测试程序的通用对象池。此对象池支持最小和最大大小。我找不到任何关于在生产中使用它的人的参考资料。有没有人这样做过?此外,在处理了 ASP.NET 应用程序中的内存碎片之后,我可以证明 Miky Dinescu 的回答中的价值。此外,稍微详细说明 Vitaly 的回答,考虑创建成本高昂的大型对象(即 > 85K)的情况。大对象只参与 Gen 2 垃圾回收。这意味着它们不会像在 Gen 0 和 Gen 1 中完全参与垃圾回收的对象那样被回收。 Maoni Stephens 在http://msdn.microsoft.com/en-us/上的这篇文章 Large Object Heap Uncovered Magazine/cc534993.aspx详细解释了大对象堆。

于 2010-12-28T16:03:28.310 回答