何时使用对象池技术?

6

何时需要使用C#的对象池?维护一个频繁使用对象的池并从中获取一个对象而不是创建一个新对象的利弊是什么?

5个回答

5

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

一个真实的例子是创建和销毁大量套接字。它们用于读/写数据的缓冲区必须固定,以便传输到本机WinSock API,这意味着当进行垃圾收集时,即使某些内存已经为被销毁的套接字回收,由于GC无法在收集后压缩堆,因此可能会导致内存处于碎片化状态。因此,读取/写入缓冲区是池化的首选候选对象。另外,如果你使用SocketEventArgs对象,那么它们也是很好的候选对象。

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


5

我只能想到两种常见的资源可以进行池化:线程和连接(即与数据库的连接)。

这两者都有一个共同的问题:稀缺性。

  • 如果创建了太多的线程,上下文切换会浪费所有的CPU时间。
  • 如果创建了太多的网络连接,维护这些连接的开销将比连接本身要更加耗费资源。
  • 此外,对于数据库来说,连接数可能因许可证限制而受到限制。

因此,您希望创建资源池的主要原因是如果您在任何时候只能负担有限数量的资源。


4
  1. 当对象创建成本很高时
  2. 当您可能会遇到内存压力 - 太多的对象(例如 - 享元模式)

1

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


0

有一篇名为“Rediscover the Lost Art of Memory Optimization in Your Managed Code”的优秀 MSDN 杂志文章,作者是 Erik Brown http://msdn.microsoft.com/en-us/magazine/cc163856.aspx。其中包括一个通用对象池及测试程序。该对象池支持最小和最大尺寸。但我找不到任何关于有人在生产中使用它的参考。有没有人这样做过?另外,作为处理 ASP.NET 应用程序中内存碎片问题的经验,我可以证明 Miky Dinescu 的答案的价值。此外,稍微详细地阐述 Vitaly 的答案,考虑创建昂贵的大对象(即 > 85K)的情况。大对象只参与第二代垃圾回收。这意味着它们不会像完全参与第 0 和第 1 代垃圾回收的对象那样被快速回收。这篇文章 Large Object Heap Uncovered,作者是 Maoni Stephens,网址为 http://msdn.microsoft.com/en-us/magazine/cc534993.aspx,详细解释了大对象堆。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接