fixes bug 328068 "gather memory usage data for load events" r=bryner

This commit is contained in:
darin%meer.net 2006-03-08 15:09:25 +00:00
Родитель 0f2e2396b0
Коммит 8f036a01aa
1 изменённых файлов: 106 добавлений и 0 удалений

Просмотреть файл

@ -48,6 +48,102 @@
#include "nsIDOMWindow.h"
#include "nsIInterfaceRequestorUtils.h"
//-----------------------------------------------------------------------------
#if defined(__linux)
#include <sys/types.h>
#include <unistd.h>
static FILE *sProcFP;
static void GetMemUsage_Shutdown() {
if (sProcFP) {
fclose(sProcFP);
sProcFP = NULL;
}
}
#elif defined(XP_WIN)
#include <windows.h>
#include <psapi.h>
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/<pid>/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()