背景: 我有一个服务,其目的是为请求者提供对象 - 它基本上从数据库中获取复杂数据并将其转换一次(有点像数据视图)以生成简化记录。然后,它根据需要提供多达10万条记录(取决于请求的性质),为其他服务的请求提供服务。
这个想法是复杂的转换只进行一次并由服务缓存 - 它比每次访问视图时让数据库更好地工作更快,并且为了我的目的工作得很好。 (我相信这被称为SSOS)
缓存数据的方式是在对象列表中,这些对象是标准.Net类型的属性包。这些对象没有引用任何其他内容。 记录将定期更改,并且必须更新缓存,这意味着必须定位,丢弃和替换原始记录。
现在缓存中的记录将在那里存在很长时间,并且已经标记为Gen 2集合;几乎所有的集合都会在Gen2阶段发生,因为这些对象长期存在(故意)。
所以我对Gen2集合的理解是它们很慢,如果集合主要用于Gen2,那么优化器会更频繁地这样做。
我希望能够以一种最终不会触发完整Gen2集合的方式取消引用列表中的对象......我想也许有一种方法可以将它标记为Gen0和然后在替换它之前取消引用它 - 但我不认为这是可能的。
我仅限于使用.Net 4,该应用程序是一项服务,可向多达100个客户提供数据,这些客户在一段时间内请求完整列表或更改列表。
问题:任何人都可以提出一种方法来以GC友好的方式取消引用长寿命对象,或者可能采用另一种方法来解决这个问题吗?
答案 0 :(得分:6)
对此没有简单的答案。如果你有很多长寿命的对象,那么完整的集合真的会受到伤害,就像我discussed here。由于一张图片说了千言万语:
那些垂直尖峰是垃圾收集发生的地方,并且会扼杀响应时间。
我们减少这种影响的方式是:没有大量长寿的物品。我们所做的是将类更改为struct
s,这意味着唯一的对象是包含它们的数组。我们很幸运的是,数据很简单,并没有涉及string
s,这当然是对象。我们还做了一些疯狂的fixed-size buffer工作来减少之前收集的内容,并将引用改为 indices (进入数组)。如果你做必须使用string
数据,也许会尽量确保你没有20,000个不同的 string
个实体具有相同的值 - 有些一种手动内插(一个Dictionary<string,string>
就够了)在那里真的很有用。
请注意,这不会影响您的公共 API,因为您始终可以从class
存储创建旧的struct
数据 - 区别在于此{{ 1}}只会作为DTO短暂存在 - 因此将在下一代0扫描中廉价收集。
YMMV,但这对我们来说效果很好。
问题是:在使用class
时,您需要非常小心;我强烈建议让它们永不变化。