C# 是否有一个.Net内存分析器可以跟踪大型对象堆上的所有分配?

C# 是否有一个.Net内存分析器可以跟踪大型对象堆上的所有分配?,c#,.net,memory-management,memory-leaks,C#,.net,Memory Management,Memory Leaks,我尝试过的大多数.NET内存分析器都允许您拍摄内存快照 然而,我正试图诊断一个问题,在这个问题上,我最终会得到分配给.NET的大量内存,这些内存被ANTS分析器指示为“空闲”。(我已经用其他探查器(如Mem探查器和CLR探查器)确认了这个问题 ANTS显示我有大量内存碎片(100%的可用内存,最大的块为150MB)。堆中所有对象的总大小为180MB。我有553MB分配给.NET,152分配给“非托管” 然而,大对象堆(LOH)的大小只有175kb。这是分配到那里的对象的实际大小。我不会分配任何永

我尝试过的大多数.NET内存分析器都允许您拍摄内存快照

然而,我正试图诊断一个问题,在这个问题上,我最终会得到分配给.NET的大量内存,这些内存被ANTS分析器指示为“空闲”。(我已经用其他探查器(如Mem探查器和CLR探查器)确认了这个问题

ANTS显示我有大量内存碎片(100%的可用内存,最大的块为150MB)。堆中所有对象的总大小为180MB。我有553MB分配给.NET,152分配给“非托管”

然而,大对象堆(LOH)的大小只有175kb。这是分配到那里的对象的实际大小。我不会分配任何永久性地落在LOH上的对象

因此,我的问题是,在这条线路的某些地方,我怀疑我不知何故分配了大型对象(LOH超过了85k的限制),然后处理它们

我正在从数据库(Oracle、Sql Server)读取大量数据(此处估计为几MB),将这些数据复制到内存中的对象数组,并将数据处理到索引(数组、字典等)中,以便于搜索/筛选/处理

我的猜测是,数据读取器暂时分配了大量空间。但是,我没有一个好方法来暂停程序并拍摄内存快照

我想要的是一个探查器,它可以跟踪LOH上分配的每个对象,这样我就可以找出导致LOH碎片和过度内存使用的原因(内存不会返回到操作系统,所以我的进程似乎需要1GB内存来存储200MB分配的对象。)我猜内存没有返回是因为LOH没有被压缩,所以在我的进程生命周期中,我会一直使用这些内存,可能需要数周(它作为windows服务运行)

编辑:我的问题是我的.NET应用程序使用了大量我无法跟踪的内存

Edit1:我使用过Visual Studio内存分析器。虽然它确实告诉我所有实例化的对象、数量、总字节数等,但我并没有告诉我为什么会有这么多空闲内存。我唯一的提示/线索是ANTS告诉我的:“内存碎片限制了可以分配的对象的大小。”我有很多未使用的内存分配给.NET,但没有使用

Edit2:更多的分析显示,我在LOH上分配了一些短期的大型对象。但是,在LOH上分配的总量从来没有超过3到4 MB。然而,在这段时间内,私有字节激增,成倍或三倍,而我实际分配的对象的大小(在所有堆上)仅略微增长。例如,所有堆中的字节数都是115MB,但我的专用字节数超过512MB

ANTS清楚地告诉我,我的内存碎片有问题。结果是我在LOH上创建了短寿命的对象。但是,这些对象的总容量从来没有超过3或4 MB。因此,这些短寿命的大型对象(似乎?)正在将LOH碎片化

回应Eric Lippert和迪斯尼乐园停车场类比(这很好)

这就像有人在一个停车点停车几分钟,然后离开。然后这个停车点就被保留了(没有人可以在那里停车),直到我重新粉刷停车场

当VisualStudio警告我内存使用情况并建议切换到x64时,我第一次开始调查这个问题。(我忘记了警告号,quick google没有找到)。因此,切换到x64可以缓解眼前的问题,但不能解决根本问题

就像我有一个可以停放1000辆车的停车场,但当我把100辆车放进去后,我的停车服务人员尖叫着说停车场已经满了

幸运的是,我有一个庞大的VMware群集供我使用,还有一个理解力强的管理员。我已经分配了8个cpu和8 GB内存。至于问题,我可以解决,我只需投入资源就可以了。此外,(正如我上面所说)不久前我切换到了x64,因为Visual Studio一直在提醒我,但是,我想弄清楚它在LOH上分配了什么,看看我是否可以通过一些小的代码更改来缓解这个堆碎片。考虑到我可以投入资源,这可能是个愚蠢的差事

该应用程序运行良好,速度很快,偶尔会出现GC暂停。但大多数情况下,我可以接受这种情况,我只想知道是什么对象导致了这种情况。我的怀疑是一些我还没有找到的短期字典

Edit3

ObjectAllocatedByClass不跟踪大对象的分配 堆,但ObjectAllocated执行。通过比较 二者,一个有进取心的灵魂应该能够弄清楚自己在做什么 与普通托管堆不同的大型对象堆


<> P>这看起来是可以做到的。然而,我的C++技巧是生疏的,可能是在未来的某个时间(如果我有更多的时间)。我希望一个分析器能提供这个方框。< /P> < P>哦上帝——EricLippert是个问题-我知道我错了——但是这里有:-/P> LOH仅存储大于85k的特定对象。我从经验中发现,这通常是字符串-XML或大型可枚举类型,它们位于全局变量和/或静态变量中

如果LOH很小,则必须在内存中存储其他对象,这些对象很可能最终成为第2代。在应用程序的整个生命周期中,这些变量可以是全局变量,如数组、字典

所以快速检查的第一件事是检查在应用程序的整个生命周期中是否存在任何变量?这些有成千上万的条目吗

其次,.NET有一个性能计数器统计每个生成大小的内存大小。国家
         Address               MT     Size
0000000012a17048 000007fee7ae6ae8   400032     
0000000012a78b00 000007fee7ae6ae8   400032     
0000000012ada5b8 000007fee7ae6ae8   400032     
0000000012b3c070 000007fee7ae6ae8   400032     
0000000012b9db28 000007fee7ae6ae8   400032
CLR Version: 4.0.30319.261
SOS Version: 4.0.30319.239
Name:        System.String
MethodTable: 000007fee7ae6ae8
EEClass:     000007fee766ed68
Size:        400026(0x61a9a) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:      8470737076787475867884758166807183888774746571677189..
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
000007fee7aec9d0  4000103        8         System.Int32  1 instance           200000 m_stringLength
000007fee7aeb510  4000104        c          System.Char  1 instance               38 m_firstChar
000007fee7ae6ae8  4000105       10        System.String  0   shared           static Empty
                                 >> Domain:Value  000000000055fe50:0000000002a11420 <<
Size:        400026(0x61a9a) bytes
String:      8470737076787475867884758166807183888774746571677189..