Jak uzyskać pamięć używaną przez program Delphi

Wiem, jak uzyskać użycie pamięci systemowej za pomocą GlobalMemoryStatusEx, ale to mówi mi, czego używa cały system operacyjny.

Naprawdę chcę, aby mój program raportował, ile pamięci sam przydzielił i używa.

Czy Jest jakiś sposób w moim programie Delphi 2009, aby wywołać funkcję Windows lub może jakąś funkcję FastMM, aby dowiedzieć się, że pamięć została przydzielona tylko przez mój program?


[[0]] Revisiting my question, I have now changed my accepted answer to the GetMemoryManagerState answer by @apenwarr. To produkowane identyczne wyniki do funkcji GetHeapStatus (teraz przestarzałe), że kiedyś używać, podczas gdy GetProcessMemoryInfo.WorkingSetSize dało zupełnie inny wynik.
Author: lkessler, 2009-01-13

5 answers

Możesz uzyskać przydatne informacje o użyciu pamięci z środowiska uruchomieniowego Delphi bez użycia bezpośrednich wywołań 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;

Najlepszą rzeczą w tej metodzie jest to, że jest ściśle śledzona: kiedy przydzielasz pamięć, idzie ona w górę, a kiedy dealokujesz pamięć, od razu spada o tę samą ilość. Używam tego przed i po uruchomieniu każdego z moich testów jednostkowych, więc mogę stwierdzić ,który test jest wyciek pamięci(na przykład).

 76
Author: apenwarr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-14 15:25:27

Z mojego starego bloga.

Chcesz wiedzieć, ile pamięci zużywa twój program? Ta funkcja Delphi załatwi sprawę.

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;

Nie jestem pewien, skąd mam podstawy tego, ale dodałem do niego lepszą obsługę błędów i zrobiłem z niej funkcję. WorkingSetSize to ilość aktualnie używanej pamięci. Możesz użyć podobnego kodu, aby uzyskać inne wartości dla bieżącego procesu (lub dowolnego procesu). Musisz uwzględnić psAPI w swoim oświadczeniu uses.

The PROCESS_MEMORY_COUNTERS zapis zawiera:

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

Wszystkie te wartości można znaleźć w Menedżerze Zadań lub Eksploratorze procesów.

 25
Author: Jim McKeeth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-14 08:26:14

Możesz spojrzeć na przykład jak używać FastMM z projektem UsageTrackerDemo, który jest dołączony do dema po pobraniu pełnego pakietu FastMM4 z SourceForge.

 4
Author: Francesca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-13 02:08:34

Napisałem tę małą funkcję, aby zwrócić bieżące zużycie pamięci procesu (aplikacji):

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;
 4
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-13 02:56:29

Dla interfejsu API Win32 potrzebna jest funkcja GetProcessMemoryInfo . Oto przykład ze strony MSDN ale kod jest w C++. Myślę, że można przekonwertować go do Delphi, jak również. To, czego szukasz, prawdopodobnie nazywa się " roboczym rozmiarem zestawu."

#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;
}
 1
Author: Gant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-13 01:34:22