C# 何时进行对象池?

C# 何时进行对象池?,c#,memory-management,object,pooling,C#,Memory Management,Object,Pooling,何时使用C#进行对象池?有什么好消息吗 维护一个频繁使用的对象池,并从池中抓取一个对象,而不是创建一个新对象,其利弊是什么 当对象创建成本很高时 当您可能遇到内存压力时-对象太多(例如,flyweight图案) 我会将内存碎片添加到列表中。当使用封装本机资源的对象时,可能会发生这种情况,在分配本机资源后,垃圾回收器无法移动本机资源,并且可能导致堆碎片化 现实生活中的一个例子是创建和销毁大量套接字。它们用于读/写数据的缓冲区必须固定,以便传输到本机WinSock API,这意味着当发生垃圾收集时,

何时使用C#进行对象池?有什么好消息吗

维护一个频繁使用的对象池,并从池中抓取一个对象,而不是创建一个新对象,其利弊是什么

  • 当对象创建成本很高时
  • 当您可能遇到内存压力时-对象太多(例如,flyweight图案)
  • 我会将内存碎片添加到列表中。当使用封装本机资源的对象时,可能会发生这种情况,在分配本机资源后,垃圾回收器无法移动本机资源,并且可能导致堆碎片化

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


    下面是一个关于垃圾收集过程、内存压缩以及为什么对象池有帮助的例子。

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

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

    • 如果创建太多线程,上下文切换将浪费所有CPU时间
    • 如果您创建了太多的网络连接,那么维护这些连接的开销将比这些连接应该做的工作更多
    • 此外,对于数据库,由于许可的原因,连接计数可能会受到限制

    因此,您希望创建资源池的主要原因是,如果您一次只能拥有有限数量的资源池。

    有一篇优秀的MSDN杂志文章,名叫Erik Brown的《在托管代码中重新发现丢失的内存优化艺术》。它包括一个带有测试程序的通用对象池。此对象池不支持最小和最大大小。我找不到任何人在生产中使用这个的参考资料。有人这样做过吗?此外,在ASP.NET应用程序中处理过内存碎片后,我可以证明Miky Dinescu的回答中的价值。另外,对维塔利的答案稍加阐述,考虑大对象(即,85 K)的情况,这是昂贵的。大型对象仅参与Gen 2垃圾收集。这意味着它们的收集速度不如第0代和第1代中完全参与垃圾收集的对象快。本文介绍了Maoni Stephens发现的大型对象堆
    at详细解释了大型对象堆。

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