Счетчик производительности для "Крупнейшего свободного региона"? - PullRequest
3 голосов
/ 13 января 2009

Я отлаживаю исключение нехватки памяти. Когда я получаю исключение, счетчик производительности «виртуальных байтов» указывает на большое количество адресуемого пространства. Проблема, однако, заключается в том, что адресуемое пространство сильно фрагментировано, а «Самый большой свободный регион» (возвращается из! Address в WinDbg) слишком мал.

Чтобы измерить фрагментацию памяти, я хотел бы отслеживать "Самый большой свободный регион" в perfmon. Есть ли счетчик производительности, который дает мне это значение?

Ответы [ 3 ]

2 голосов
/ 14 января 2009

Я не верю, что для этой информации есть единый счетчик производительности, но его можно определить с помощью функции VirtualQueryEx Win32.

Вы можете вызвать его по минимальному действительному виртуальному адресу (который можно получить из GetSystemInfo), затем вы можете использовать размер возвращаемого диапазона страниц, чтобы определить базовый адрес следующего диапазона страниц, для которого вызывать VirtualQueryEx.

Проходя по адресному пространству с повторными вызовами на VirtualQueryEx, вы можете определить самый большой диапазон страниц типа MEM_FREE и его базовый адрес.

Это метод, который я использовал для своей программы 'Address Space Monitor'.

1 голос
/ 13 января 2009

С http://dotnetdebug.net/2005/06/30/perfmon-your-debugging-buddy/:

Индикаторы фрагментации виртуального адресного пространства:

  • Общее количество зарезервированных байтов, значительно превышающее # общее количество принятых байтов
  • Количество прикрепленных объектов увеличивается
  • Количество ручек ГХ увеличивается
  • Количество байтов во всех кучах всегда увеличивается.
0 голосов
/ 01 октября 2015

Используя код, который я нашел здесь , вот пример кода Чарльз Бэйли решение :

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...