c# - 优化长生命周期对象的收集

标签 c# optimization garbage-collection

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

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

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

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

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

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

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

问题:谁能建议一种以 GC 友好的方式取消引用长期存在的对象的方法,或者可能是另一种方法来解决这个问题?

最佳答案

对此没有简单的答案。如果你有很多长期存在的对象,那么完整的集合真的会造成伤害,就像我一样 discussed here .一张图说一千个字:

enter image description here

那些垂直尖峰是垃圾收集发生的地方,并且会缩短响应时间。

我们减少这种影响的方法是:不要拥有无数的长生命周期对象。我们所做的是将类更改为 struct s,这意味着唯一的对象 是包含它们的数组。我们在这里很幸运,数据很简单,不涉及 string。 s,它们本身当然是对象。我们也做了一些疯狂的事fixed-size buffer努力减少以前的集合,并将引用更改为索引(进入数组)。如果您确实必须使用string数据,也许尝试确保您没有 20,000 个不同 string具有相同值的实例 - 某种手动内部工具(Dictionary<string,string> 就足够了)在那里可能非常有用。

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

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

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

关于c# - 优化长生命周期对象的收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15294326/

相关文章:

c# - child 对象与 parent 的沟通模式

r - 循环数据优化算法

android - 在 Android 中优化位图创建/调整大小

java - 当Java线程设置为null时会发生什么?

java - java中String的垃圾回收

java - 如何去掉java程序的垃圾回收时间?

c# - 具有不同节点路径的 XPath

c# - 具有匿名类型和用户定义类型的 LINQ 选择查询

c# - 在运行时,如何测试属性是否为只读?

python - 如何将 0/1 转换为高效签名?