我有一项服务随着时间的推移间歇性地开始吞噬服务器内存,需要重新启动才能释放它。我用 gflags 转为 +ust,重新启动服务,并开始拍摄预定的 UMDH 快照。当问题再次发生时,资源管理器在工作集和私有字节下报告了多个 GB,但 UMDH 快照仅占进程堆中的几个 MB 分配。
在 UMDH 快照文件的顶部,它提到“仅转储堆管理器收集堆栈的分配”。
当指定 +ust 标志时,进程中的分配怎么会没有痕迹?
如何找出这些 GB 的分配位置/方式?
我有一项服务随着时间的推移间歇性地开始吞噬服务器内存,需要重新启动才能释放它。我用 gflags 转为 +ust,重新启动服务,并开始拍摄预定的 UMDH 快照。当问题再次发生时,资源管理器在工作集和私有字节下报告了多个 GB,但 UMDH 快照仅占进程堆中的几个 MB 分配。
在 UMDH 快照文件的顶部,它提到“仅转储堆管理器收集堆栈的分配”。
当指定 +ust 标志时,进程中的分配怎么会没有痕迹?
如何找出这些 GB 的分配位置/方式?
UMDH 是用户模式转储堆的缩写。术语堆在这里是一个关键术语:它仅指 C++ 堆管理器。这意味着通过 C++ 堆管理器以外的其他方式分配的所有内存都不会被 UMDH 跟踪。
这可以是
VirtualAlloc()
但即使对于 C++,也存在 C++ 堆管理器无法有效管理大于 512 kB 的分配的情况,因此它只是将其重定向到VirtualAlloc()
并且不会创建如此大分配的堆段。
如何找出这些 GB 的分配位置/方式?
对于直接调用VirtualAlloc()
,WinDbg 命令!address -summary
可能会给出答案。对于.NET,SOS 扩展和!dumpheap -stat
可以给出答案。