1

是否有用于获取有关 VM 使用的详细信息的 .NET API?我对确定我的地址空间的碎片化程度特别感兴趣。

谢谢!

4

5 回答 5

1

简短的回答:没有。为此,您需要利用 Win32 API。我真的不知道你会使用什么 API 调用......

http://www.pinvoke.net上快速搜索让我发现了这一点:

[DllImport("coredll.dll", SetLastError=true)]
static extern void GlobalMemoryStatus(ref MEMORYSTATUS lpBuffer);

但是 MEMORYSTATUS 结构似乎没有您需要的所有信息(只是物理和虚拟内存使用情况和其他信息)。

您应该在 MSDN 周围挖掘以找到必要的方法。

于 2010-01-22T17:37:35.437 回答
1

可以让您对此有所了解的 Windows API 函数类型是 VirtualQueryEx(),用于枚举虚拟内存部分并发现未使用的空间,GetProcessHeaps() 用于查找在进程内创建的堆,以及 HeapWalk(),用于发现块如何进入每个堆都被使用。

这并不容易,尤其是 HeapWalk() 在正在运行的程序中是一个麻烦的函数。你应该看看 SysInternals 的VMMap 实用程序,它提供了出色的虚拟内存诊断。

这样做的缺点是它并不能真正帮助您解决内存碎片问题。您无法影响 Windows 内存管理器子分配虚拟内存空间的方式。短于不分配内存。如果您现在正在为 OOM 苦苦挣扎,那么您真的应该考虑重新构建您的应用程序。或者切换到 64 位操作系统,两百美元的解决方案。

于 2010-01-22T19:31:20.643 回答
0

这样的调用在托管世界中没有意义,因为不同的 CLR 主机可能处理不同的事情(如普通应用程序主机或 SQL Server)。并且不要忘记 GC 可以移动东西,因此碎片并不是真正的问题,因为 GC 压缩了堆。

但是,这让我想到了下一点,您应该能够通过自己托管 CLR 来获取此信息。您可能想查看有关此主题的博客文章

于 2010-01-22T17:41:16.740 回答
0

您确实必须深入了解 Win32/Win64 API 才能在页面级别获取此信息。更详细,您需要了解您正在查看的任何堆的内部工作原理,无论是 C 堆、Win32 堆、CLR 小对象堆还是 CLR 大对象堆。

但是,您可以使用Virtual Memory Validator(它是商业的,但免费的)来可视化虚拟内存空间,并且还可以逐页和逐段检查内存空间。首先查看视觉效果,因为这样可以很容易地看到一般问题和趋势。当您确定哪些内存区域有问题时,请查看页面和段落的详细信息。

这是一篇描述什么是页面和段落的博客文章。

于 2010-03-16T17:22:38.110 回答
0

在 C 中,您可以编写类似这样的内容来了解​​分配了多少内存:

HANDLE heap = GetProcessHeap();
PROCESS_HEAP_ENTRY entry;
memset(&entry, 0, sizeof(entry));
unsigned long size = 0;
while(HeapWalk(heap, &entry)) {
    if(entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) {
        size += entry.cbData;
    }
}

如果使用其他堆,则可能需要 GetProcessHeaps(),在这种情况下,您需要第二个循环来遍历所有堆。我不知道为什么他们会不止一个。

在您的情况下,您可能应该计算块的数量及其大小。如果你想把它保存到磁盘,我建议你先计算块的数量,分配一个缓冲区来保存所有信息,然后将缓冲区保存在一个文件中以供以后查看。

于 2011-04-06T00:35:13.790 回答