Thursday, July 5, 2012

CE: Memory Monitoring

Memory leaks can be a pain in the ass. But memory leaks that only shows up after a long period of testing would kill all the excitement in your development. Well this happened in my work (yes those times that I've been away from this blog). In memory of that experience I'll share here a few tricks that worked for me.  

I'll start with  MEMORYSTATUS, this is defined in MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366772%28v=vs.85%29.aspx

You can use this to gather system specific memory status.Here's a snippet of what I did:
===================================================
                // Log Memory Status at this time
                file = fopen(gMemLogFilename, "a");
                if(file)
                {
                    fprintf(file, "\nLog %8d:", logCount);
                 
                    // Get Memory details
                    GlobalMemoryStatus(&memstatus);
                    fprintf(file, "%8d:", memstatus.dwMemoryLoad);
                    fprintf(file, "%8d:", memstatus.dwTotalPhys/1024);
                    fprintf(file, "%8d:", memstatus.dwAvailPhys/1024);
                    fprintf(file, "%8d:", memstatus.dwTotalPageFile/1024);
                    fprintf(file, "%8d:", memstatus.dwAvailPageFile/1024);
                    fprintf(file, "%8d:", memstatus.dwTotalVirtual/1024);
                    fprintf(file, "%8d:", memstatus.dwAvailVirtual/1024);
                   
                    // Get physical disk space
                    GetDiskFreeSpaceEx(_T("\\Flash File Store"),&notused,&totalBytes,&freeBytes);
                    fprintf(file, "%8d:", totalBytes.QuadPart/1024);
                    fprintf(file, "%8d:", freeBytes.QuadPart/1024);

                    GetDiskFreeSpaceEx(_T("\\My Device"),&notused,&totalBytes,&freeBytes);
                    fprintf(file, "%8d:", totalBytes.QuadPart/1024);
                    fprintf(file, "%8d:", freeBytes.QuadPart/1024);

                    fclose(file);
                }

I separate the values with colon(:) so that I can export the log to excel and trace how the memory consumption performs over time. I put this inside a loop that checks the memory at specific intervals. This a very useful tool if you do stress testing (those tests that need more than a day to finish...i.e. hopper, battery, etc.)

=======================================================================
If your not contented with system level monitoring. You can even dig to which process is taking most of your memory. Use PROCVMINFO. This structure is not documented in MSDN but should work for all WinCE/WinMobile platform. Here's how to use it.

 DWORD total = 0;
 PROCVMINFO vmi = { 0 };
 HANDLE procID = 0;

     for( int idx = 0; idx < 33; ++idx )
    {
        memset(&vmi, 0, sizeof(PROCVMINFO));
        if( ::CeGetProcVMInfo( idx, sizeof( PROCVMINFO ), &vmi ) )
        {
            procID = GetProcessIDFromIndex(idx);
           
            AddProcessInfoToList((DWORD)procID, vmi.cbRwMemUsed/1024);//You can use this function for as data collector
            total += vmi.cbRwMemUsed;
        }

    }

======================================================================
For system that suddenly become slow over time, I would also suggest to the percentage of the system process being idle. Here's how to do it:

    DWORD dwStartTick, dwIdleSt, dwStopTick,dwIdleEd;

    dwStartTick = GetTickCount();
    dwIdleSt = GetIdleTime();
    //  Insert a call to the Sleep(sleep_time) function to allow idle time
    //  to accrue. An example of an appropriate sleep time is 1000 ms.
    Sleep(1000);
    dwStopTick = GetTickCount();
    dwIdleEd = GetIdleTime();

    return ((100*(dwIdleEd - dwIdleSt)) / (dwStopTick - dwStartTick));

No comments: