Performance counter for the Largest Free Region?

I am debugging an exception from memory. When I get an exception, the "virtual byte" performance counter points to a lot of address spaces. The problem, however, is that the address space is highly fragmented, and the "largest free area" (returned from! Addresses in WinDbg) is too small.

To measure memory fragmentation, I would like to track the “Biggest Free Region” in perfmon. Is there a performance counter that gives me this value?

+3
source share
3 answers

I do not think that there is a single performance counter for this piece of information, but it can be displayed using the VirtualQueryExWin32 function .

You can call it at the minimum valid virtual address (which can be obtained from GetSystemInfo), then you can use the size of the returned page range to determine the base address of the next page range for which to call VirtualQueryEx.

By going through an address space with repeated calls to VirtualQueryExlike this, you can determine the largest range of pages of type MEM_FREE and its base address.

This is the method that I used for my Address Space Monitor program.

+2
source

, , Charles Bailey :

public class MemoryAnalyzer {
    public long GetLargestFreeRegionSize() {
        // getting minimum & maximum address
        SYSTEM_INFO sysInfo;
        GetSystemInfo(out sysInfo);

        var procMinAddress = sysInfo.minimumApplicationAddress;
        var procMaxAddress = sysInfo.maximumApplicationAddress;

        // saving the values as long ints so I won't have to do a lot of casts later
        var procMinAddressL = (long)procMinAddress;
        var procMaxAddressL = (long)procMaxAddress;

        // current process
        var process = Process.GetCurrentProcess();

        // opening the process with desired access level
        var processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_WM_READ, false, process.Id);

        long maxFreeRegionSize = 0;

        while (procMinAddressL < procMaxAddressL) {
            const int memBasicInfoSize = 28; //sizeof(MEMORY_BASIC_INFORMATION)
            MEMORY_BASIC_INFORMATION memBasicInfo;
            VirtualQueryEx(processHandle, procMinAddress, out memBasicInfo, memBasicInfoSize);

            if (memBasicInfo.State == MEM_FREE) {
                maxFreeRegionSize = Math.Max(maxFreeRegionSize, memBasicInfo.RegionSize);
            }

            // move to the next memory chunk
            procMinAddressL += memBasicInfo.RegionSize;
            procMinAddress = new IntPtr(procMinAddressL);
        }

        return maxFreeRegionSize;
    }

    #region Win32
    // REQUIRED CONSTS
    const int PROCESS_QUERY_INFORMATION = 0x0400;
    const int PROCESS_WM_READ = 0x0010;
    const int MEM_FREE = 0x10000;

    // REQUIRED METHODS
    [DllImport("kernel32.dll")]
    public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

    [DllImport("kernel32.dll")]
    public static extern bool ReadProcessMemory(int hProcess, int lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);

    [DllImport("kernel32.dll")]
    static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength);

    // REQUIRED STRUCTS
    public struct MEMORY_BASIC_INFORMATION {
        public int BaseAddress;
        public int AllocationBase;
        public int AllocationProtect;
        public int RegionSize;
        public int State;
        public int Protect;
        public int lType;
    }

    public struct SYSTEM_INFO {
        public ushort processorArchitecture;
        ushort reserved;
        public uint pageSize;
        public IntPtr minimumApplicationAddress;
        public IntPtr maximumApplicationAddress;
        public IntPtr activeProcessorMask;
        public uint numberOfProcessors;
        public uint processorType;
        public uint allocationGranularity;
        public ushort processorLevel;
        public ushort processorRevision;
    }
    #endregion
}
0

All Articles