4

背景:我有一项服务,其生活目的是为请求者提供对象-它基本上从数据库中获取复杂的数据并将其转换一次(有点像数据视图)以生成简化的记录。然后通过按需提供多达 100k 条记录(取决于请求的性质)来处理来自其他服务的请求。

这个想法是复杂的转换完成一次并由服务缓存 - 它比每次访问视图时让数据库解决它更快,并且对于我的目的来说工作得很好。(我相信这被某些人称为 SSOS)

缓存数据的方式是在一个对象列表中,这些对象是标准 .Net 类型的属性包。这些对象没有对其他任何东西的引用。记录会定期更改,并且必须更新缓存,这意味着必须定位、丢弃和替换原始记录。

现在缓存中的记录将在其中保存很长时间,并已被标记为 Gen 2 集合;几乎所有的收集都将发生在 Gen2 阶段,因为这些对象已经存在了很长时间(故意)。

所以我对 Gen2 集合的理解是它们很慢,如果集合主要在 Gen2 上工作,那么优化器会更频繁地执行此操作。

我希望能够以一种不会最终触发完整 Gen2 集合的方式取消引用列表中的对象...我在想也许有一种方法将其标记为 Gen0 然后取消-在替换它之前引用它 - 但我认为这是不可能的。

我被限制为此使用 .Net 4,并且该应用程序是一项服务,可为多达 100 个在一段时间内请求完整列表或更改列表的客户提供数据。

问题:任何人都可以提出一种以 GC 友好的方式或另一种解决此问题的方法来取消引用长寿命对象的方法吗?

4

1 回答 1

8

对此没有简单的答案。如果你有很多长寿命的对象,那么完整的集合真的会受到伤害,正如我在这里讨论的那样。既然一张图讲了一千个字:

在此处输入图像描述

这些垂直尖峰是垃圾收集发生并扼杀响应时间的地方。

我们减少这种影响的方法是:不要有无数长寿命的物体。我们所做的是将类更改为structs,这意味着唯一的对象是包含它们的数组。幸运的是,这里的数据很简单,不涉及strings,当然它们本身就是对象。我们还做了一些疯狂的固定大小缓冲区工作,以减少以前集合的内容,并更改对索引的引用(到数组中)。如果您确实必须使用数据,也许尝试确保您没有 20,000个具有相同值的不同实例 - 某种手动内部人员(astring stringDictionary<string,string>就足够了)在那里真的很有用。

请注意,这不会影响您的公共API,因为您始终可以class从存储中创建旧数据struct- 不同之处在于这class将仅作为 DTO 短暂存在 - 因此将在下一次 gen-0 扫描中廉价收集。

YMMV,但这对我们来说已经足够好了。

问题是:使用 s 时需要非常小心struct;我强烈建议使它们不可变。

于 2013-03-08T12:54:04.460 回答