2009-01-12 5 views
3

Je débogue une exception de mémoire insuffisante. Lorsque j'obtiens l'exception, le compteur de performance "octets virtuels" indique beaucoup d'espace adressable. Le problème, cependant, est que l'espace adressable est gravement fragmenté, et la "plus grande région libre" (retournée par! Adresse dans WinDbg) est trop petite.Compteur de performance pour "La plus grande région libre"?

Pour mesurer la fragmentation de la mémoire, je voudrais surveiller la "plus grande région libre" dans perfmon. Y a-t-il un compteur de performance qui me donne cette valeur?

Répondre

2

Je ne crois pas qu'il existe un seul compteur de performance pour cette information, mais il peut être déduit en utilisant la fonction Win32 VirtualQueryEx.

Vous pouvez l'appeler avec l'adresse virtuelle valide minimale (qui peut être obtenue à partir de GetSystemInfo), vous pouvez ensuite utiliser la taille de la plage de pages renvoyée pour déterminer l'adresse de base de la plage de pages suivante pour laquelle appeler VirtualQueryEx. En parcourant l'espace adresse avec des appels répétés à VirtualQueryEx de cette manière, vous pouvez déterminer la plus grande plage de pages du type MEM_FREE et quelle est son adresse de base.

C'est la technique que j'ai utilisée pour mon programme 'Address Space Monitor'.

1

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

Adresse virtuelle Espace Fragmentation Indicateurs:

  • Nombre total d'octets réservés nettement plus grand que # total engagé Octets
  • Nombre d'objets épinglées augmentation
  • Nombre de poignées GC
  • Le nombre d'octets dans tous les tas augmente toujours.
+0

Ce sont là quelques bons indicateurs, mais les pires délinquants sont en réalité en dehors de .NET dans C DLLs que les fichiers de carte mémoire . Ces indicateurs supposent que le problème est visible sous forme de .NET, mais malheureusement ce n'est pas dans mon cas. – Sean

+0

Si vous pouviez regarder les octets réservés par rapport aux octets validés, cela vous donnerait une meilleure idée. Je ne vois pas un compteur comme ça. MSN – MSN

0

En utilisant le code que j'ai trouvé here, voici un exemple de code de solution de 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 
} 
Questions connexes