开发者

.NET API for determining VM fragmentation

开发者 https://www.devze.com 2022-12-17 16:08 出处:网络
Is there a .NET API for getting det开发者_运维问答ailed info on VM use? I\'m specifically interested in determining how fragmented my address space is.

Is there a .NET API for getting det开发者_运维问答ailed info on VM use? I'm specifically interested in determining how fragmented my address space is.

Thanks!


The kind of Windows API functions that can give you some insight in this are VirtualQueryEx() to enumerate the virtual memory sections and discover unused space, GetProcessHeaps() to find what heaps are created inside the process and HeapWalk() to discover how blocks in each heap are used.

This is not going to be easy, particularly HeapWalk() is a troublesome function in a running program. You ought to take a look at the SysInternals' VMMap utility, it provides excellent virtual memory diagnostics.

The downfall with this is that it doesn't really help you solve a memory fragmentation problem. There is nothing you can do to affect the way the Windows memory manager sub-allocates the virtual memory space. Short from not allocating memory. If you are struggling now with OOM, you really ought to consider re-architecting your app. Or switching to a 64-bit operating system, the two hundred dollar solution.


Short answer: no. You need to tap into the Win32 API for that. I really don't know what API call you would use though...

A quick search on http://www.pinvoke.net led me to this:

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

But the MEMORYSTATUS struct doesn't seem to have all the info you need (just physical & virtual memory usage and other info).

You should dig around MSDN to find the necessary method.


Such a call doesn't make sense in the managed world, since different CLR hosts may handle things different (like the normal application host or SQL Server). And don't forget that the GC can move things around, so that the fragmentation isn't really a problem is the GC compacts the heap.

However, this brings me to the next point, you should be able to get this information by hosting the CLR yourself. You may want to look at this blog post about this topic.


You really have to get down into the Win32/Win64 API to get this information at the page level. Any more detailed and you need to know the internal workings of whichever heap you are looking at, whether its a C heap, Win32 heap, a CLR small object heap or a CLR large object heap.

However you can use Virtual Memory Validator (which is commercial, but free) to visualise the virtual memory space, and also examine the memory space page by page and paragraph by paragraph. Look at the visuals first as that makes it easy to see general problems and trends. Then look at the detailed info on pages and paragraphs when you've decided what memory areas are problematic.

Here is a blog article describing what pages and paragraphs are.


In C you can write something like this to know how much memory is allocated:

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;
    }
}

The GetProcessHeaps() may be required if other heaps are used in which case you need a second loop to go through all the heaps. I don't know why their would be more than one though.

In your case, you should probably count the number of blocks and their sizes. If you want to save that to disk, I suggest you first count the number of blocks, allocate a buffer to save all the information, then save the buffer in a file for later review.

0

精彩评论

暂无评论...
验证码 换一张
取 消