代码之家  ›  专栏  ›  技术社区  ›  lkessler

如何获取Delphi程序使用的内存

  •  41
  • lkessler  · 技术社区  · 16 年前

    我知道如何使用GlobalMemoryStatusEx获得系统内存使用,但这告诉我整个操作系统在使用什么。

    我真的想让我的程序报告它自己分配和使用了多少内存。

    在我的Delphi 2009程序中,是否有任何方法可以调用Windows函数或某个FastMM函数来查找仅由我的程序分配的内存?


    再次回顾我的问题,我现在已将已接受的答案更改为@apenwarr提供的getMemoryManager状态答案。它产生了与我以前使用的GetHeapStatus函数(现在已弃用)相同的结果,而GetProcessMemoryInfo.WorkingSetSize给出了非常不同的结果。

    6 回复  |  直到 14 年前
        1
  •  80
  •   lkessler    5 年前

    您可以从Delphi运行时获取有用的内存使用信息,而无需使用任何直接Win32调用:

    unit X;
    
    uses  FastMM4; //include this or method will return 0.
    ....
    
    function GetMemoryUsed: UInt64;
    var
      st: TMemoryManagerState;
      sb: TSmallBlockTypeState;
    begin
      GetMemoryManagerState(st);
      result :=  st.TotalAllocatedMediumBlockSize
               + st.TotalAllocatedLargeBlockSize;
      for sb in st.SmallBlockTypeStates do begin
        result := result + sb.UseableBlockSize * sb.AllocatedBlockCount;
      end;
    end;
    

    这种方法最好的地方在于它是严格跟踪的:当你分配内存时,它会上升,当你释放内存时,它会立即下降相同的数量。我在运行每一个单元测试之前和之后都会使用它,因此我可以判断哪个测试正在泄漏内存(例如)。

        2
  •  26
  •   Jim McKeeth    16 年前

    From an old blog post of mine

    想知道你的程序正在使用多少内存吗?这个Delphi函数将完成这个任务。

    uses psAPI;
    
    {...}
    
    function CurrentProcessMemory: Cardinal;
    var
      MemCounters: TProcessMemoryCounters;
    begin
      MemCounters.cb := SizeOf(MemCounters);
      if GetProcessMemoryInfo(GetCurrentProcess,
          @MemCounters,
          SizeOf(MemCounters)) then
        Result := MemCounters.WorkingSetSize
      else
        RaiseLastOSError;
    end;
    

    这个 进程\内存\计数器 记录包括:

    • 页面错误计数
    • 工作设置大小
    • QuotaPeakPagedPoolUsage
    • QuotaNonPagedPoolUsage
    • 页面文件使用
    • PeakPagefileUsage

    您可以在任务管理器或Process Explorer中找到所有这些值。

        3
  •  4
  •   Francesca    16 年前

    当您从SourceForge下载完整的FastMM4捆绑包时,您可以查看一个示例,说明如何将FastMM与演示附带的UsageTrackerDemo项目一起使用。

        4
  •  4
  •   user34411 user34411    16 年前

    function ProcessMemory: longint;
    var
      pmc: PPROCESS_MEMORY_COUNTERS;
      cb: Integer;
    begin
      // Get the used memory for the current process
      cb := SizeOf(TProcessMemoryCounters);
      GetMem(pmc, cb);
      pmc^.cb := cb;
      if GetProcessMemoryInfo(GetCurrentProcess(), pmc, cb) then
         Result:= Longint(pmc^.WorkingSetSize);
    
      FreeMem(pmc);
    end;
    
        5
  •  2
  •   Maicon Fernando    7 年前

    转换 Gant C++代码,用于Delphi中的控制台应用程序:

        program MemoryProcessCMD;
    
        {* Based in Gant(https://stackoverflow.com/users/12460/gant) code*}
    
    
        {$APPTYPE CONSOLE}
        {$R *.res}
    
        uses
          System.SysUtils,
          psapi,
          Windows;
    
        procedure PrintMemoryInfo(processID: DWORD);
        var
          hProcess: THandle;
          pmc: PROCESS_MEMORY_COUNTERS;
          total: DWORD;
    
        begin
    
          // Print the process identifier.
          Writeln(format('Process ID: %d', [processID]));
    
          // Print information about the memory usage of the process.
          hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, FALSE,
            processID);
    
          if (hProcess = 0) then
          begin
            exit;
          end;
    
          if (GetProcessMemoryInfo(hProcess, @pmc, SizeOf(pmc))) then
          begin
            Writeln(format(#09'PageFaultCount: 0x%.8X', [pmc.PageFaultCount]));
            Writeln(format(#09'PeakWorkingSetSize: 0x%.8X', [pmc.PeakWorkingSetSize]));
            Writeln(format(#09'WorkingSetSize: 0x%.8X', [pmc.WorkingSetSize]));
            Writeln(format(#09'QuotaPeakPagedPoolUsage: 0x%.8X',
              [pmc.QuotaPeakPagedPoolUsage]));
            Writeln(format(#09'QuotaPagedPoolUsage: 0x%.8X',
              [pmc.QuotaPagedPoolUsage]));
            Writeln(format(#09'QuotaPeakNonPagedPoolUsage: 0x%.8X',
              [pmc.QuotaPeakNonPagedPoolUsage]));
            Writeln(format(#09'QuotaNonPagedPoolUsage: 0x%.8X',
              [pmc.QuotaNonPagedPoolUsage]));
            Writeln(format(#09'PagefileUsage: 0x%.8X', [pmc.PagefileUsage]));
            Writeln(format(#09'PeakPagefileUsage: 0x%.8X', [pmc.PeakPagefileUsage]));
            Writeln(format(#09'PagefileUsage: 0x%.8X', [pmc.PagefileUsage]));
          end;
    
          CloseHandle(hProcess);
        end;
    
        var
          aProcesses: array [0 .. 1024] of DWORD;
          cbNeeded, cProcesses: DWORD;
          i: Integer;
    
        begin
          try
            // Get the list of process identifiers.
            if (not EnumProcesses(@aProcesses, SizeOf(aProcesses), &cbNeeded)) then
              halt(1);
    
            // Calculate how many process identifiers were returned.
            cProcesses := cbNeeded div SizeOf(DWORD);
    
            // Print the memory usage for each process
            for i := 0 to cProcesses - 1 do
            begin
              PrintMemoryInfo(aProcesses[i]);
            end;
          except
            on E: Exception do
              Writeln(E.ClassName, ': ', E.Message);
          end;
    
        end.
    
        6
  •  1
  •   Gant    16 年前

    对于Win32 API方式,您需要 GetProcessMemoryInfo 作用这里有一个来自中国的例子 MSDN page

    #include <windows.h>
    #include <stdio.h>
    #include <psapi.h>
    
    void PrintMemoryInfo( DWORD processID )
    {
        HANDLE hProcess;
        PROCESS_MEMORY_COUNTERS pmc;
    
        // Print the process identifier.
    
        printf( "\nProcess ID: %u\n", processID );
    
        // Print information about the memory usage of the process.
    
        hProcess = OpenProcess(  PROCESS_QUERY_INFORMATION |
                                        PROCESS_VM_READ,
                                        FALSE, processID );
        if (NULL == hProcess)
            return;
    
        if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) )
        {
            printf( "\tPageFaultCount: 0x%08X\n", pmc.PageFaultCount );
            printf( "\tPeakWorkingSetSize: 0x%08X\n", 
                      pmc.PeakWorkingSetSize );
            printf( "\tWorkingSetSize: 0x%08X\n", pmc.WorkingSetSize );
            printf( "\tQuotaPeakPagedPoolUsage: 0x%08X\n", 
                      pmc.QuotaPeakPagedPoolUsage );
            printf( "\tQuotaPagedPoolUsage: 0x%08X\n", 
                      pmc.QuotaPagedPoolUsage );
            printf( "\tQuotaPeakNonPagedPoolUsage: 0x%08X\n", 
                      pmc.QuotaPeakNonPagedPoolUsage );
            printf( "\tQuotaNonPagedPoolUsage: 0x%08X\n", 
                      pmc.QuotaNonPagedPoolUsage );
            printf( "\tPagefileUsage: 0x%08X\n", pmc.PagefileUsage ); 
            printf( "\tPeakPagefileUsage: 0x%08X\n", 
                      pmc.PeakPagefileUsage );
        }
    
        CloseHandle( hProcess );
    }
    
    int main( )
    {
        // Get the list of process identifiers.
    
        DWORD aProcesses[1024], cbNeeded, cProcesses;
        unsigned int i;
    
        if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
            return 1;
    
        // Calculate how many process identifiers were returned.
    
        cProcesses = cbNeeded / sizeof(DWORD);
    
        // Print the memory usage for each process
    
        for ( i = 0; i < cProcesses; i++ )
            PrintMemoryInfo( aProcesses[i] );
    
        return 0;
    }