2013-03-08 60 views
2

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

这个想法是,复杂的转换只需完成一次,然后通过服务进行缓存 - 比每次访问视图时都要让数据库解决问题的速度更快,而且对于我的目的而言工作得很好。 (我相信这是由一些所谓的SSOS)

数据被缓存的方式是在为物业袋标准.NET类型对象的列表。这些对象没有任何其他引用。 定期记录将会改变,并且必须更新缓存,这意味着原始记录必须被定位,丢弃并被替换。

现在在高速缓存中的记录会一直在那里很长一段时间,并会被标记为第2代集合;几乎所有的收藏品都会在Gen2阶段发生,因为这些物品已经存在了很长时间(有意)。

所以我的第二代收藏的理解是,他们是缓慢的,如果集合工作主要是在第二代则优化会更经常地做到这一点。

我希望能够以引用完整Gen2集合的方式去除列表中的某个对象......我想也许有一种将它标记为Gen0的方法然后在更换之前取消参考 - 但我认为这是不可能的。

我不得不使用.NET 4中,这和应用是用作数据多达100个客户端请求谁完整列表,或更改列表一段时间的服务。

问题:任何人都可以提出一个方式去参考长期生活的对象在GC友好的方式或者是另一种方式来解决这个问题?

+3

您目前是否有任何内存/性能问题? – ken2k 2013-03-08 12:50:33

+0

是的,它在内存使用上运行很热。我把它降到了1GB(峰值) - 但它正在做很多处理 - 在同时查询/序列化/向大量客户端提供大量数据时,最高可以使用高达70%的cpu。这就是为什么我已经开始关注GC性能,看看我能做些什么来获得大量的处理能力。我知道我也有一个线程问题 - 但不认为我可以(或者想 - 我需要让管理层有理由移到4.5!)修复,直到我能够移动到.net 4.5并使用异步/等待模型释放线程。 – Jay 2013-03-08 12:54:22

+0

@Jay注意到由此引起的GC perf将限于周期性尖峰(通常相当可预测/均匀间隔)。它不会改变*集合之间的性能*。所以,如果你的应用程序已经很热,你可能会看错了。 – 2013-03-08 12:56:10

回答

6

对此没有简单的答案。如果你有很多长寿命的物品,那么完整的收藏品真的会受到伤害,因为我discussed here。由于图片讲述了千言万语:

enter image description here

那些垂直尖峰其中垃圾收集发生和屠杀的响应时间。

我们减少这种影响的方式是:没有gazillion长寿命的物体。我们所做的是将类更改为struct s,这意味着唯一的对象是包含它们的数组。我们幸运的是,数据很简单,并没有涉及到string,这当然本身就是对象。我们也做了一些疯狂的fixed-size buffer工作,以减少的事情,以前的集合,并改变了什么是引用指数(进入阵列)。如果您必须使用string数据,也许尽量确保您不会有20,000个警报不同string instancs具有相同值 - 某种手工interner的(一个Dictionary<string,string>就足够了),可以真正有用的存在。

注意,这种需求不会影响您的公共 API,因为你总是可以创建一个从struct存储旧class数据 - 不同的是,这将class只是简单地存在,作为一个DTO - 因此将收集便宜在下一代gen-0扫描中。

YMMV,但这对我们来说工作得不错。

问题是:您需要是真的谨慎使用struct s;我强烈建议让他们不变。

+0

感谢这篇伟大的文章,并给我新的想法。 – Jay 2013-03-08 14:43:06