Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Process Memory Usage in C on Windows

Tags:

c

windows

I want record the memory usage of my program. Here is a example.

#include <stdio.h>
#include <windows.h>
#include <psapi.h>

void getMemInfo(){
    PROCESS_MEMORY_COUNTERS_EX pmc;
    GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS *)&pmc, sizeof(pmc));
    SIZE_T virtualMemUsedByMe = pmc.PrivateUsage;
    SIZE_T physMemUsedByMe = pmc.WorkingSetSize;
    printf("%ld, %ld\n", virtualMemUsedByMe, physMemUsedByMe);
}
int main()
{
    double a[1000];
    
    getMemInfo();
    double *b = malloc(sizeof(double)*1000);
    
    getMemInfo();
    free(b);

    getMemInfo();
    return 0;
}

I compile it and run it three times;

enter image description here

Well. Now I have few questions.

  • Why does the usage of my program [or my program output] change every time? Did I use the wrong parameters of pmc?
  • How to record the memory usage of c program in time before and after allocating new memory?
  • I want to optimize a c project. So I should use which parameter of pmc as a benchmark?

Refer:

  • Collecting Memory Usage Information For a Process
  • c++ - How to determine CPU and memory consumption from inside a process - Stack Overflow
like image 680
Lex Avatar asked Sep 18 '26 21:09

Lex


1 Answers

I think you allocated a very small size in double *b; allocate uses memory in the heap. So your process already have some free heap size. To see the change in process memory usage, you must allocate space more than the current heap size minute the free heap size.

Try:

#include <windows.h>
#include <psapi.h>
#pragma comment( lib, "psapi.lib" )
#include <malloc.h>

long HeapUsed()
{
_HEAPINFO info = { 0, 0, 0 };
long used = 0;
int rc;

while ((rc=_heapwalk(&info)) == _HEAPOK)
{
    if (info._useflag == _USEDENTRY)
        used += info._size;
}
if (rc != _HEAPEND && rc != _HEAPEMPTY)
    used = (used?-used:-1);

return used;
}


unsigned long GetHeapInitializedSize(HANDLE heap)
{
unsigned long sz = 0;
HeapLock(heap);
PROCESS_HEAP_ENTRY entry;
memset(&entry, '\0', sizeof entry);
while (HeapWalk(heap, &entry))
{
    if (entry.wFlags != PROCESS_HEAP_UNCOMMITTED_RANGE)
    {
        sz += entry.cbData + entry.cbOverhead;
    }
}
HeapUnlock(heap);
return sz;
}
#include <intsafe.h>


int _tmain(int argc, _TCHAR* argv[])
{

DWORD NumberOfHeaps;
HRESULT Result;
PHANDLE aHeaps;
SIZE_T BytesToAllocate;
HANDLE hDefaultProcessHeap;
long heap_size;
DWORD processID;
HANDLE hProcess;
long heap_used_size;
long heap_free_size;
PROCESS_MEMORY_COUNTERS pmc;
NumberOfHeaps = GetProcessHeaps(0, NULL);
Result = SIZETMult(NumberOfHeaps, sizeof(*aHeaps), &BytesToAllocate);
hDefaultProcessHeap = GetProcessHeap();
heap_size = GetHeapInitializedSize(hDefaultProcessHeap);
processID =  GetProcessId(GetCurrentProcess());
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID );
heap_used_size = HeapUsed();



char *b = (char*)malloc(sizeof(char)*(heap_size - heap_used_size + 1024));
if (GetProcessMemoryInfo(  hProcess, &pmc, sizeof(pmc)))
{
    printf( "\tWorkingSetSize: 0x%08X - %u\n",  pmc.WorkingSetSize,  
        pmc.WorkingSetSize / 1024);        
    printf( "\tQuotaPeakPagedPoolUsage: 0x%08X - %u\n", 
        pmc.QuotaPeakPagedPoolUsage ,   pmc.QuotaPeakPagedPoolUsage / 1024);
    printf( "\tQuotaPagedPoolUsage: 0x%08X - %u\n", pmc.QuotaPagedPoolUsage, 
        pmc.QuotaPagedPoolUsage / 1024);
    printf( "\tQuotaPeakNonPagedPoolUsage: 0x%08X - %u\n", 
        pmc.QuotaPeakNonPagedPoolUsage,pmc.QuotaPeakNonPagedPoolUsage / 1024 );
    printf( "\tQuotaNonPagedPoolUsage:0x%08X-%u\n",pmc.QuotaNonPagedPoolUsage ,   pmc.QuotaNonPagedPoolUsage / 1024);
    printf( "\tPagefileUsage: 0x%08X - %u\n", pmc.PagefileUsage,     pmc.PagefileUsage/1024 ); 
    printf( "\tPeakPagefileUsage: 0x%08X - %u\n", pmc.PeakPagefileUsage, pmc.PeakPagefileUsage/1024 );
    printf( "\tcb: 0x%08X - %u\n", pmc.cb , pmc.cb / 1024);     
}

free(b);
if (GetProcessMemoryInfo(  hProcess, &pmc, sizeof(pmc)))
{
    printf( "\tWorkingSetSize: 0x%08X - %u\n",  pmc.WorkingSetSize,  
        pmc.WorkingSetSize / 1024);        
    printf( "\tQuotaPeakPagedPoolUsage: 0x%08X - %u\n", 
        pmc.QuotaPeakPagedPoolUsage ,   pmc.QuotaPeakPagedPoolUsage / 1024);
    printf( "\tQuotaPagedPoolUsage: 0x%08X - %u\n", pmc.QuotaPagedPoolUsage, 
        pmc.QuotaPagedPoolUsage / 1024);
    printf( "\tQuotaPeakNonPagedPoolUsage: 0x%08X - %u\n", 
        pmc.QuotaPeakNonPagedPoolUsage,pmc.QuotaPeakNonPagedPoolUsage / 1024 );
    printf( "\tQuotaNonPagedPoolUsage:0x%08X-%u\n",pmc.QuotaNonPagedPoolUsage ,   pmc.QuotaNonPagedPoolUsage / 1024);
    printf( "\tPagefileUsage: 0x%08X - %u\n", pmc.PagefileUsage,     pmc.PagefileUsage/1024 ); 
    printf( "\tPeakPagefileUsage: 0x%08X - %u\n", pmc.PeakPagefileUsage, pmc.PeakPagefileUsage/1024 );
    printf( "\tcb: 0x%08X - %u\n", pmc.cb , pmc.cb / 1024);     
}

Why does the usage of my program [or my program output] change every time? Did I use the wrong parameters of pmc?

That’s because you use printf. Try this:

SIZE_T arr[5][2];
int cur_index = 0;

void getMemInfo(){
     PROCESS_MEMORY_COUNTERS_EX pmc;
     SIZE_T virtualMemUsedByMe;
     SIZE_T physMemUsedByMe;
     GetProcessMemoryInfo(GetCurrentProcess(), 
(PROCESS_MEMORY_COUNTERS *)&pmc, sizeof(pmc));
virtualMemUsedByMe = pmc.PrivateUsage;
physMemUsedByMe = pmc.WorkingSetSize;
arr[cur_index][0] = virtualMemUsedByMe;
arr[cur_index][1] = physMemUsedByMe;
cur_index++;
}



int _tmain(int argc, _TCHAR* argv[])
{
   for(int u = 0; u < 5; u++) {
      getMemInfo();
      Sleep(1000);
   }

    for(int u = 0; u < 5; u++) 
      fprintf(stdout,"%ld, %ld\n", arr[u][0], arr[u][1]);

I got

860160, 4681728
860160, 4681728
860160, 4681728
860160, 4681728
860160, 4681728
like image 200
Evlampii Avatar answered Sep 21 '26 11:09

Evlampii