我有一个大型应用程序,内存分配平均大约30 mb / sec(每个性能监视器字节分配/秒测量)。我试图大幅削减这一点,而且分配的来源并不明显。
为了检测我记录了CLR / GC的ETW跟踪,并导出了AllocationTick事件,该事件每次分配额外的100千字节时记录,以及最近分配的对象类型。这会产生一个很好的大小样本集。三种对象类型占我的分配的70%,但它们有点神秘。
数据集大约需要70分钟和100万个事件,所以我对这些数字非常有信心。
我猜这是在某种程度上表明我以一些意想不到的方式在堆上创建了很多指针? (这是一个x64应用程序)
我使用了一些linq和foreach循环,但这些只应该在堆栈上创建增量变量,而不是堆。
我也在TPL / Dataflow库之上运行所有内容,这可能会生成这些内容。
我正在寻找关于可能导致如此多的int32 / 64堆分配的建议,也许还有一些隔离这些分配的技术(调用堆栈会很好,但可能性能过高)。
答案 0 :(得分:5)
我猜这是在某种程度上表明我是以某种意想不到的方式在堆上创建了很多指针?
听起来你更有可能向我提出很多int
和long
值。
CallSite
部分听起来好像你经常使用dynamic
(或者在一个非常频繁使用的部分代码中),这很容易导致拳击比静态类型代码更多。< / p>
我会尝试隔离分配了很多对象的代码的特定区域 - 例如,如果你可以只运用特定的代码路径,这会让你更清楚地了解哪些路径产生的垃圾比你期待的。查看使用dynamic
的任何地方,看看您是否确实需要 - 尽管您不应该认为必须以任何方式删除对dynamic
的所有使用;可能有一个特殊的“热点”可以进行微观优化。
要考虑的另一件事是这个分配实际上花了多少钱。你说你试图大幅削减它 - 你真的需要吗?如果所有这些对象都非常短暂,您可能会发现通过降低分配率不会大大提高性能。您应该测量垃圾收集所花费的时间,以确定其可能的有效性。