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

发布于 2024-07-10 21:49:04 字数 351 浏览 8 评论 0原文

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

我真的希望我的程序报告它单独分配和正在使用多少内存。

我的 Delphi 2009 程序中是否有任何方法可以调用 Windows 函数或某些 FastMM 函数来找出由我的程序单独分配的内存?


重新审视我的问题,我现在已将我接受的答案更改为 @apenwarr 的 GetMemoryManagerState 答案。 它产生的结果与我以前使用的 GetHeapStatus 函数(现已弃用)相同,而 GetProcessMemoryInfo.WorkingSetSize 给出了非常不同的结果。

I know how to get the System memory use using GlobalMemoryStatusEx, but that tells me the what the entire OS is using.

I really want my program to report how much memory it alone has allocated and is using.

Is there any way within my Delphi 2009 program to call either a Windows function or maybe some FastMM function to find out the memory that has been allocated by my program alone?


Revisiting my question, I have now changed my accepted answer to the GetMemoryManagerState answer by @apenwarr. It produced identical results to the GetHeapStatus function (now deprecated) that I used to use, whereas GetProcessMemoryInfo.WorkingSetSize gave a very different result.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

太阳男子 2024-07-17 21:49:04

您可以从 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;

此方法的最佳之处在于它是严格跟踪的:当您分配内存时,它会增加,而当您释放内存时,它会减少立即相同的金额。 我在运行每个单元测试之前和之后使用它,这样我就可以知道哪个测试正在泄漏内存(例如)。

You can get useful memory usage information out of the Delphi runtime without using any direct Win32 calls:

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;

The best thing about this method is that it's strictly tracked: when you allocate memory, it goes up, and when you deallocate memory, it goes down by the same amount right away. I use this before and after running each of my unit tests, so I can tell which test is leaking memory (for example).

相守太难 2024-07-17 21:49:04

来自旧博客我的帖子

想知道您的程序使用了多少内存? 这个 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;

不确定我从哪里获得了这方面的基础知识,但我为其添加了一些更好的错误处理并使其成为一个函数。 WorkSetSize 是当前使用的内存量。 您可以使用类似的代码来获取当前进程(或任何进程)的其他值。 您需要在使用语句中包含 psAPI。

PROCESS_MEMORY_COUNTERS 记录包括:

  • PageFaultCount
  • PeakWorkingSetSize
  • WorkSetSize
  • QuotaPeakPagedPoolUsage
  • QuotaPagedPoolUsage
  • QuotaPeakNonPagedPoolUsage
  • QuotaNonPagedPoolUsage
  • PagefileUsage
  • PeakPagefileUsage

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

From an old blog post of mine.

Want to know how much memory your program is using? This Delphi function will do the trick.

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;

Not sure where I got the basics of this, but I added some better error handling to it and made it a function. WorkingSetSize is the amount of memory currently used. You can use similar code to get other values for the current process (or any process). You will need to include psAPI in your uses statement.

The PROCESS_MEMORY_COUNTERS record includes:

  • PageFaultCount
  • PeakWorkingSetSize
  • WorkingSetSize
  • QuotaPeakPagedPoolUsage
  • QuotaPagedPoolUsage
  • QuotaPeakNonPagedPoolUsage
  • QuotaNonPagedPoolUsage
  • PagefileUsage
  • PeakPagefileUsage

You can find all of these values in Task Manager or Process Explorer.

梦途 2024-07-17 21:49:04

当您从 SourceForge 下载完整的 FastMM4 捆绑包时,您可以查看有关如何将 FastMM 与UsageTrackerDemo 项目一起使用的示例,该项目包含在演示中。

You can look at an example on how to use FastMM with the UsageTrackerDemo project that comes included with the Demos when you download the complete FastMM4 bundle from SourceForge.

我爱人 2024-07-17 21:49:04

我编写了这个小函数来返回当前进程(应用程序)的内存使用情况:

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;

I wrote this small function to return the current process (app) memory usage:

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;
不语却知心 2024-07-17 21:49:04

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.

Conversion of Gant C ++ code, to console application in 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.
从此见与不见 2024-07-17 21:49:04

对于Win32 API方式,您需要GetProcessMemoryInfo函数。 以下是 MSDN 页面 中的示例,但代码是C++的。 我想你也可以将它转换为Delphi。 您正在寻找的可能称为“工作集大小”。

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

For Win32 API way, you need GetProcessMemoryInfo function. Here is an example from MSDN page but the code is in C++. I think you can convert it to Delphi as well. What you are looking is probably called "Working Set Size."

#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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文