From 8f036a01aa8afdcbc0d83b5d19be16b28c98b4ce Mon Sep 17 00:00:00 2001 From: "darin%meer.net" Date: Wed, 8 Mar 2006 15:09:25 +0000 Subject: [PATCH] fixes bug 328068 "gather memory usage data for load events" r=bryner --- extensions/metrics/src/nsLoadCollector.cpp | 106 +++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/extensions/metrics/src/nsLoadCollector.cpp b/extensions/metrics/src/nsLoadCollector.cpp index 051cd51234bc..698cf39f444d 100644 --- a/extensions/metrics/src/nsLoadCollector.cpp +++ b/extensions/metrics/src/nsLoadCollector.cpp @@ -48,6 +48,102 @@ #include "nsIDOMWindow.h" #include "nsIInterfaceRequestorUtils.h" +//----------------------------------------------------------------------------- + +#if defined(__linux) +#include +#include +static FILE *sProcFP; +static void GetMemUsage_Shutdown() { + if (sProcFP) { + fclose(sProcFP); + sProcFP = NULL; + } +} +#elif defined(XP_WIN) +#include +#include +typedef BOOL (WINAPI * GETPROCESSMEMORYINFO_FUNC)( + HANDLE process, PPROCESS_MEMORY_COUNTERS counters, DWORD cb); +static HMODULE sPSModule; +static HANDLE sProcess; +static GETPROCESSMEMORYINFO_FUNC sGetMemInfo; +static void GetMemUsage_Shutdown() { + if (sProcess) { + CloseHandle(sProcess); + sProcess = NULL; + } + if (sPSModule) { + FreeLibrary(sPSModule); + sPSModule = NULL; + } + sGetMemInfo = NULL; +} +#endif + +struct MemUsage { + PRInt64 total; + PRInt64 resident; +}; + +// This method should be incorporated into NSPR +static PRBool GetMemUsage(MemUsage *result) +{ + PRBool setResult = PR_FALSE; +#if defined(__linux) + // Read /proc//statm, and look at the first and second fields, which + // report the program size and the number of resident pages for this process, + // respectively. + + char buf[256]; + if (!sProcFP) { + pid_t pid = getpid(); + snprintf(buf, sizeof(buf), "/proc/%d/statm", pid); + sProcFP = fopen(buf, "rb"); + } + if (sProcFP) { + int vmsize, vmrss; + + int count = fscanf(sProcFP, "%d %d", &vmsize, &vmrss); + rewind(sProcFP); + + if (count == 2) { + static int ps = getpagesize(); + result->total = PRInt64(vmsize) * ps; + result->resident = PRInt64(vmrss) * ps; + setResult = PR_TRUE; + } + } +#elif defined(XP_WIN) + // Use GetProcessMemoryInfo, which only works on WinNT and later. + + if (!sGetMemInfo) { + sPSModule = LoadLibrary("psapi.dll"); + if (sPSModule) { + sGetMemInfo = (GETPROCESSMEMORYINFO_FUNC) + GetProcAddress(sPSModule, "GetProcessMemoryInfo"); + if (sGetMemInfo) + sProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + FALSE, GetCurrentProcessId()); + // Don't leave ourselves partially initialized. + if (!sProcess) + GetMemUsage_Shutdown(); + } + } + if (sGetMemInfo) { + PROCESS_MEMORY_COUNTERS pmc; + if (sGetMemInfo(sProcess, &pmc, sizeof(pmc))) { + result->total = PRInt64(pmc.PagefileUsage); + result->resident = PRInt64(pmc.WorkingSetSize); + setResult = PR_TRUE; + } + } +#endif + return setResult; +} + +//----------------------------------------------------------------------------- + static nsLoadCollector *gLoadCollector = nsnull; NS_IMPL_ISUPPORTS2(nsLoadCollector, @@ -150,6 +246,14 @@ nsLoadCollector::OnStateChange(nsIWebProgress *webProgress, rv = props->SetPropertyAsUint64(NS_LITERAL_STRING("loadtime"), loadTime); NS_ENSURE_SUCCESS(rv, rv); + MemUsage mu; + if (GetMemUsage(&mu)) { + rv = props->SetPropertyAsUint64(NS_LITERAL_STRING("memtotal"), mu.total); + NS_ENSURE_SUCCESS(rv, rv); + rv = props->SetPropertyAsUint64(NS_LITERAL_STRING("memresident"), mu.resident); + NS_ENSURE_SUCCESS(rv, rv); + } + nsMetricsService *ms = nsMetricsService::get(); rv = ms->LogEvent(NS_LITERAL_STRING("load"), props); @@ -220,6 +324,8 @@ nsLoadCollector::Shutdown() // See comments in nsWindowCollector::Shutdown about why we don't // null out gLoadCollector here. gLoadCollector->Release(); + + GetMemUsage_Shutdown(); } nsLoadCollector::~nsLoadCollector()