【问题标题】:When to go for object pooling?什么时候使用对象池?
【发布时间】:2010-04-15 14:51:52
【问题描述】:

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

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

【问题讨论】:

    标签: c# memory-management object pooling


    【解决方案1】:

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

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

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

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

    【讨论】:

      【解决方案2】:

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

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

      这是一个good article,它讨论了垃圾收集过程、内存压缩以及对象池为何有帮助。

      【讨论】:

        【解决方案3】:
        1. 对象创建成本高时
        2. 当您可能会遇到内存压力时 - 对象太多(例如 - 享元模式)

        【讨论】:

          【解决方案4】:

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

          【讨论】:

            【解决方案5】:

            有一篇出色的 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 的这篇文章 Large Object Heap Uncovered athttp://msdn.microsoft.com/en-us/magazine/cc534993.aspx详细讲解大对象堆。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2014-05-03
              • 1970-01-01
              • 2013-01-05
              • 2023-04-10
              • 1970-01-01
              • 1970-01-01
              • 2015-08-08
              • 2023-03-24
              相关资源
              最近更新 更多