C# Int/Int64.Net内存分配

C# Int/Int64.Net内存分配,c#,.net,memory-management,garbage-collection,heap,C#,.net,Memory Management,Garbage Collection,Heap,我有一个大型应用程序,它的内存分配平均约为30 mb/秒(按性能监视器字节分配/秒度量)。我正试图大幅削减这一数额,而拨款的来源并不明显 为了检测事物,我记录了CLR/GC的ETW跟踪,并导出了AllocationTick事件,该事件记录了每次额外分配100 KB的时间,以及最近分配的对象类型。这产生了一个很好的样本集。三种对象类型占我分配的70%,但它们有点神秘 System.Int6430% System.Int3228% System.Runtime.CompilerServices.Ca

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

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

  • System.Int6430%
  • System.Int3228%
  • System.Runtime.CompilerServices.CallSite'1[System.Func'3[System.Runtime.CompilerServices.CallSite,System.Object,System.Object]12%
  • 数据集是大约70分钟和100万个事件,所以我对这些数字很有信心

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

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

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

    我正在寻找关于是什么导致int32/64的堆分配如此之多的建议,也许还有一些隔离这些分配的技术(调用堆栈会很好,但性能可能会很高)

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

    对我来说,听起来更像是在装箱很多
    int
    long

    CallSite
    部分听起来像是在大量使用
    dynamic
    (或者在代码中使用非常频繁的部分),这很容易导致比静态类型代码更多的装箱

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


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

    动态洞察是一个巨大的提示。我只在少数地方使用dynamic进行调试,在相同的调试代码中,我将装箱结果。谢谢另一方面-难以置信的帮助和快速响应。我不知道你什么时候睡觉才能像现在这样有反应(现在是加利福尼亚州的午夜)。分配是短暂的,但由于Gen-0收集导致我们的应用程序中出现一些厚尾事件,它们每秒会触发多次暂停。@Superman:我在一周的欧洲/伦敦时间大约从午夜睡到早上6点,周末从午夜到早上7点:)听起来你正处于一个非常理想的优化状态,只有几个热点——总是一个很好的位置。