3

我有一个大型应用程序,其内存分配平均约为 30 mb/秒(每个性能监视器分配的字节数/秒测量)。我正试图大幅减少这一点,而分配的来源并不明显。

为了检测事物,我记录了 CLR / GC 的 ETW 跟踪,并导出了 AllocationTick 事件,该事件记录每次额外分配 100 KB 时,以及最近分配的对象类型是什么。这会产生一个大小合适的样本集。三种对象类型占我分配的 70%,但它们有点神秘。

  1. System.Int64 30%
  2. System.Int32 28%
  3. System.Runtime.CompilerServices.CallSite'1[System.Func'3[System.Runtime.CompilerServices.CallSite,System.Object,System.Object]] 12%

数据集大约 70 分钟和一百万个事件,所以我对这些数字很有信心。

我猜这在某种程度上表明我以某种意想不到的方式在堆上创建了很多指针?(这是一个 x64 应用程序)

我使用了一些 linq 和 foreach 循环,但这些应该只在堆栈上创建增量变量,而不是在堆上。

我也在 TPL / Dataflow 库之上运行所有东西,这可能会生成这些。

我正在寻找有关可能导致这么多 int32/64 堆分配的任何建议,也许还有一些隔离这些分配的技术(调用堆栈会很棒,但性能可能会令人望而却步)。

4

1 回答 1

5

我猜这在某种程度上表明我以某种意想不到的方式在堆上创建了很多指针?

听起来你更有可能对我进行很多拳击intlong价值观。

CallSite部分听起来你使用dynamic了很多(或在代码的一个非常频繁使用的部分),这很容易导致比静态类型代码更多的装箱。

我会尝试隔离分配大量对象的代码的特定区域 - 例如,如果您可以只使用特定的代码路径,这将使您更清楚地了解哪些路径会产生比您更多的垃圾预计。看看任何使用的地方,dynamic看看你是否真的需要——尽管你不应该觉得你必须以任何方式删除所有的使用dynamic;很可能有一个特定的“热点”可以进行微优化。

要考虑的另一件事是这种分配实际上花费了您多少。你说你正试图大幅减少它——你真的需要吗?如果所有这些对象的生命周期都很短,那么您很可能会发现通过降低分配率并不能提高性能。您应该测量垃圾收集所花费的时间,以确定这可能是多么有效。

于 2013-09-08T06:34:31.797 回答