Windows 用于检测内存泄漏的内存指标
Windows memory metric to detect memory leak
我们有大量旧的遗留服务器代码 运行 作为 64 位 windows 服务。
该服务存在内存泄漏,目前我们没有资源修复。
由于该服务可以弹性重启,我们想要的临时可怕 'solution' 是检测服务的内存何时超过,例如 5GB,并退出服务(对于这种情况会自动重启)。
我的问题是我应该选择哪个指标?正在使用 GlobalMemoryStatusEx
获取
MEMORYSTATUSEX.ullTotalVirtual- MEMORYSTATUSEX.ullAvailVirtual
对吗?
GlobalMemoryStatusEx
是错误的。在总共剩余 5 GB 之前,您不想填满机器内存。
你需要GetProcessMemoryInfo
.
BOOL WINAPI GetProcessMemoryInfo(
__in HANDLE Process,
__out PPROCESS_MEMORY_COUNTERS ppsmemCounters,
__in DWORD cb
);
来自 example using GetProcessMemoryInfo
:
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
// To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS
// and compile with -DPSAPI_VERSION=1
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( "\tWorkingSetSize: 0x%08X\n", pmc.WorkingSetSize );
printf( "\tPagefileUsage: 0x%08X\n", pmc.PagefileUsage );
}
CloseHandle( hProcess );
}
int main( void )
{
// 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;
}
虽然不直观,但您需要阅读 PagefileUsage
,这会让您获得由您的进程分配的已提交内存。 WorkingSetSize
不可靠,因为如果机器内存紧张,OS 会将所有数据写入页面文件。这可能会导致 WorkingSetSize
变小(例如 100 MB),但实际上您已经泄漏了 20 GB 的内存。这将导致内存消耗呈锯齿状,直到页面文件已满。工作集只是活跃使用的内存,如果机器处于内存压力下,可能会隐藏多 GB 的内存泄漏。
我们有大量旧的遗留服务器代码 运行 作为 64 位 windows 服务。 该服务存在内存泄漏,目前我们没有资源修复。
由于该服务可以弹性重启,我们想要的临时可怕 'solution' 是检测服务的内存何时超过,例如 5GB,并退出服务(对于这种情况会自动重启)。
我的问题是我应该选择哪个指标?正在使用 GlobalMemoryStatusEx
获取
MEMORYSTATUSEX.ullTotalVirtual- MEMORYSTATUSEX.ullAvailVirtual
对吗?
GlobalMemoryStatusEx
是错误的。在总共剩余 5 GB 之前,您不想填满机器内存。
你需要GetProcessMemoryInfo
.
BOOL WINAPI GetProcessMemoryInfo(
__in HANDLE Process,
__out PPROCESS_MEMORY_COUNTERS ppsmemCounters,
__in DWORD cb
);
来自 example using GetProcessMemoryInfo
:
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
// To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS
// and compile with -DPSAPI_VERSION=1
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( "\tWorkingSetSize: 0x%08X\n", pmc.WorkingSetSize );
printf( "\tPagefileUsage: 0x%08X\n", pmc.PagefileUsage );
}
CloseHandle( hProcess );
}
int main( void )
{
// 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;
}
虽然不直观,但您需要阅读 PagefileUsage
,这会让您获得由您的进程分配的已提交内存。 WorkingSetSize
不可靠,因为如果机器内存紧张,OS 会将所有数据写入页面文件。这可能会导致 WorkingSetSize
变小(例如 100 MB),但实际上您已经泄漏了 20 GB 的内存。这将导致内存消耗呈锯齿状,直到页面文件已满。工作集只是活跃使用的内存,如果机器处于内存压力下,可能会隐藏多 GB 的内存泄漏。