我正在编写一个金融C#应用程序,它接收来自网络的消息,根据消息类型将它们转换为不同的对象,最后将应用程序业务逻辑应用于它们.
关键是在应用业务逻辑之后,我非常确定我将永远不再需要这个实例.我不想等待垃圾收集器释放它们,而是明确地"删除"它们.
有没有更好的方法在C#中这样做,我应该使用一个对象池来重用总是相同的实例集,还是有更好的策略.
目标是避免垃圾收集在时间关键过程中使用任何CPU.
不要马上删除它们.为每个对象调用垃圾收集器是个坏主意.通常情况下,你真的不想与垃圾收集混乱可言,甚至时间关键过程都只是比赛条件等,如果他们是敏感的事情发生.
但是,如果你知道你的应用程序对于轻载时段很忙,那么当你到达一个光照期以鼓励在下一个繁忙时段之前进行清理时,你可以尝试更通用的GC.Collect().
看这里:http://msdn.microsoft.com/en-us/library/bb384202.aspx
你可以告诉垃圾收集器你现在正在做一些关键的事情,它会对你很好.
你打了自己 - 使用一个对象池并重用这些对象.对这些对象的调用的语义需要隐藏在工厂外观后面.您需要以某种预定义的方式扩展池.每次达到极限时可能会增加一倍的尺寸 - 高水算法或固定百分比.我强烈建议你不要调用GC.Collect().
当池上的负载变得足够低时,您可以缩小池并最终触发垃圾收集 - 让CLR担心它.
尝试对垃圾收集器进行二次猜测通常是一个非常糟糕的主意.在Windows上,垃圾收集器是一代的,可以依赖它非常有效.这个一般规则有一些值得注意的例外 - 最常见的是一个事件的发生,你知道一个事实会导致很多旧的对象死亡 - 一旦对象被提升为Gen2(最长寿命)他们往往会四处闲逛.
在你提到的情况下,你听起来好像在生成一些短期对象 - 这些将导致Gen0集合.无论如何,这些都经常发生,并且是最有效的.如果您愿意,可以通过拥有可重用的对象池来避免它们,但最好在采取此类操作之前确定GC是否是性能问题 - CLR分析器是执行此操作的工具.
应该注意的是,垃圾收集器在不同的.NET框架上是不同的 - 在紧凑的框架上(在Xbox 360和移动平台上运行)它是一个非世代的GC,因此你必须更加小心什么你的程序产生的垃圾.
强制GC.Collect()通常是一个坏主意,让GC做它最擅长的事情.听起来最好的解决方案是使用可以在必要时增长的对象池 - 我已成功使用此模式.
这样,您不仅可以避免垃圾收集,还可以避免常规分配成本.
最后,您确定GC导致您出现问题吗?在实施任何节能解决方案之前,您应该测量并证明这一点 - 您可能会造成不必要的工作!
"目标是避免垃圾收集在时间关键过程中使用任何CPU"
问:如果时间紧迫,你的意思是说你正在听一些神秘的硬件,你不能错过中断?
答:如果是这样,那么C#不是要使用的语言,你需要汇编程序,C或C++.
问:如果时间严重,你的意思是管道中有很多消息,而你不想让垃圾收集器放慢速度?
答:如果是这样,你会不必要地担心.通过物体的声音,你的物体非常短暂,这意味着垃圾收集器将非常有效地回收它们,而没有任何明显的性能滞后.
然而,唯一可以确定的方法是测试它,将其设置为一夜之间运行处理恒定的测试消息流,如果你的性能统计数据可以在GC启动时发现,我会感到震惊(即使你可以发现它,如果真的很重要,我会更加惊讶).