From 6ae224960784d4a7ebd15e404408e79b640bc430 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 28 Aug 2006 18:22:07 +0000 Subject: [PATCH] memory usage svn path=/trunk/boinc/; revision=11020 --- checkin_notes | 20 ++++++++ client/app.C | 33 ++++++++++++- client/log_flags.C | 1 + client/log_flags.h | 1 + lib/procinfo.h | 14 +++++- lib/procinfo_win.C | 85 ++++++++++++++++++++++++++++----- win_build/boinc_cli_curl.vcproj | 8 ++++ 7 files changed, 147 insertions(+), 15 deletions(-) diff --git a/checkin_notes b/checkin_notes index 706aae185f..4307a1454d 100755 --- a/checkin_notes +++ b/checkin_notes @@ -9401,3 +9401,23 @@ Charlie 28 Aug 2006 clientgui/ AdvancedFrame.cpp,h Events.h + +David 28 Aug 2006 + - Detection of memory usage now works on Windows. + You can find the amount of RAM (working set) + and page file spaced used by each running BOINC app, + and by all non-BOINC apps. + Currently this isn't used for anything. + If you set the flag in cc_config.xml, + it will print memory stats every 10 seconds. + + TODO: get this working for Linux/Mac + + client/ + app.C + log_flags.C,h + lib/ + procinfo.h + procinfo_win.h + win_build/ + boinc_cli_curl.vcproj diff --git a/client/app.C b/client/app.C index 92432e7978..b9e8810bdf 100644 --- a/client/app.C +++ b/client/app.C @@ -67,6 +67,7 @@ #include "shmem.h" #include "util.h" #include "client_msgs.h" +#include "procinfo.h" #include "app.h" using std::max; @@ -199,6 +200,7 @@ void ACTIVE_TASK_SET::free_mem() { // bool ACTIVE_TASK_SET::poll() { bool action; + unsigned int i; static double last_time = 0; if (gstate.now - last_time < 1.0) return false; last_time = gstate.now; @@ -210,7 +212,7 @@ bool ACTIVE_TASK_SET::poll() { process_control_poll(); action |= check_rsc_limits_exceeded(); action |= get_msgs(); - for (unsigned int i=0; itask_state == PROCESS_ABORT_PENDING) { if (gstate.now > atp->abort_time + 5.0) { @@ -222,6 +224,35 @@ bool ACTIVE_TASK_SET::poll() { if (action) { gstate.set_client_state_dirty("ACTIVE_TASK_SET::poll"); } + + if (log_flags.mem_usage_debug) { + static double last_mem_time=0; + if (gstate.now - last_mem_time > 10) { + last_mem_time = gstate.now; + vector piv; + PROCINFO pi; + procinfo_setup(piv); + for (i=0; itask_state == PROCESS_EXECUTING) { + memset(&pi, 0, sizeof(pi)); + pi.id = atp->pid; + procinfo_app(pi, piv); + msg_printf(NULL, MSG_INFO, "%s: RAM %dKB, page %dKB, user %f, kernel %f", + atp->result->name, + (int)(pi.working_set_size/1024), (int)(pi.swap_size/1024), + pi.user_time, pi.kernel_time + ); + } + } + procinfo_other(pi, piv); + msg_printf(NULL, MSG_INFO, "All others: RAM %dKB, page %dKB, user %f, kernel %f", + (int)(pi.working_set_size/1024), (int)(pi.swap_size/1024), + pi.user_time, pi.kernel_time + ); + } + } + return action; } diff --git a/client/log_flags.C b/client/log_flags.C index ad3c58e97b..d2a49e69a3 100644 --- a/client/log_flags.C +++ b/client/log_flags.C @@ -87,6 +87,7 @@ int LOG_FLAGS::parse(XML_PARSER& xp) { else if (xp.parse_bool(tag, "guirpc_debug", guirpc_debug)) continue; else if (xp.parse_bool(tag, "scrsave_debug", scrsave_debug)) continue; else if (xp.parse_bool(tag, "app_msg_debug", app_msg_debug)) continue; + else if (xp.parse_bool(tag, "mem_usage_debug", mem_usage_debug)) continue; else { msg_printf(NULL, MSG_ERROR, "Unrecognized tag in %s: <%s>\n", CONFIG_FILE, tag diff --git a/client/log_flags.h b/client/log_flags.h index 440ed985eb..87d27b5f1b 100644 --- a/client/log_flags.h +++ b/client/log_flags.h @@ -65,6 +65,7 @@ struct LOG_FLAGS { bool guirpc_debug; bool scrsave_debug; bool app_msg_debug; // show shared-mem message from apps + bool mem_usage_debug; // memory usage LOG_FLAGS(); int parse(XML_PARSER&); diff --git a/lib/procinfo.h b/lib/procinfo.h index 45c8a2bcce..fab04a677d 100644 --- a/lib/procinfo.h +++ b/lib/procinfo.h @@ -1,10 +1,20 @@ #include struct PROCINFO { - double virtual_size; + int id; + int parentid; + double swap_size; double working_set_size; double user_time; double kernel_time; + bool is_boinc_app; }; -extern int get_procinfo(std::vector& pi). +extern int procinfo_setup(std::vector&); + // call this first to get data structure +extern void procinfo_app(PROCINFO&, std::vector&); + // call this to get mem usage for a given app + // (marks process as BOINC) +extern void procinfo_other(PROCINFO&, std::vector&); + // After getting mem usage for all BOINC apps, + // call this to get mem usage for everything else diff --git a/lib/procinfo_win.C b/lib/procinfo_win.C index b4a1fba205..c2faafb3d3 100644 --- a/lib/procinfo_win.C +++ b/lib/procinfo_win.C @@ -1,6 +1,19 @@ -#include "diagnostic_win.h" +#include "diagnostics_win.h" #include "procinfo.h" +using std::vector; + +// NtQuerySystemInformation +typedef NTSTATUS (WINAPI *tNTQSI)( + ULONG SystemInformationClass, + PVOID SystemInformation, + ULONG SystemInformationLength, + PULONG ReturnLength +); + +// OpenThread +typedef HANDLE (WINAPI *tOT)(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId); + static int get_process_information(PVOID* ppBuffer, PULONG pcbBuffer) { int retval = 0; NTSTATUS Status = STATUS_INFO_LENGTH_MISMATCH; @@ -40,7 +53,6 @@ int get_procinfo_XP(vector& pi) { ULONG cbBuffer = 32*1024; // 32k initial buffer PVOID pBuffer = NULL; PSYSTEM_PROCESSES pProcesses = NULL; - PSYSTEM_THREADS pThread = NULL; HMODULE hKernel32Lib; tOT pOT = NULL; @@ -51,10 +63,15 @@ int get_procinfo_XP(vector& pi) { pProcesses = (PSYSTEM_PROCESSES)pBuffer; while (pProcesses) { PROCINFO p; - p.virtual_size = pProcesses->VmCounters.VirtualSize; + p.id = pProcesses->ProcessId; + p.parentid = pProcesses->InheritedFromProcessId; + p.swap_size = pProcesses->VmCounters.PagefileUsage; p.working_set_size = pProcesses->VmCounters.WorkingSetSize; - p.user_time = (double) pProcesses->UserTime.QuadPart; - p.kernel_time = (double) pProcesses->KernelTime.QuadPart; + p.user_time = ((double) pProcesses->UserTime.QuadPart)/1e7; + p.kernel_time = ((double) pProcesses->KernelTime.QuadPart)/1e7; + p.id = pProcesses->ProcessId; + p.parentid = pProcesses->InheritedFromProcessId; + p.is_boinc_app = false; pi.push_back(p); if (!pProcesses->NextEntryDelta) { @@ -66,14 +83,16 @@ int get_procinfo_XP(vector& pi) { if (pBuffer) HeapFree(GetProcessHeap(), NULL, pBuffer); return 0; } -int get_procinfo_NT(vector& pi) { +int get_procinfo_NT(vector&) { return 0; } -int get_procinfo_9X(vector& pi) { +int get_procinfo_9X(vector&) { return 0; } -int get_procinfo(vector& pi) { +// get a list of all running processes. +// +int procinfo_setup(vector& pi) { OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(osvi); GetVersionEx(&osvi); @@ -83,7 +102,7 @@ int get_procinfo(vector& pi) { switch(osvi.dwPlatformId) { case VER_PLATFORM_WIN32_WINDOWS: // Win95, Win98, WinME - return get_procinfo_9x(pi); + return get_procinfo_9X(pi); case VER_PLATFORM_WIN32_NT: switch(osvi.dwMajorVersion) { case 4: @@ -97,11 +116,53 @@ int get_procinfo(vector& pi) { // WinVista return get_procinfo_XP(pi); } else { - return get_procinfo_9x(pi); + return get_procinfo_9X(pi); } default: - return get_procinfo_9x(pi); + return get_procinfo_9X(pi); } } - return get_procinfo_9x(pi); + return get_procinfo_9X(pi); } + +// scan the process table from the given point, +// adding in CPU time and mem usage +// +void add_proc_totals(PROCINFO& pi, vector& piv, int pid, int start) { + unsigned int i; + for (i=start; i& piv) { + add_proc_totals(pi, piv, pi.id, 0); +} + +void procinfo_other(PROCINFO& pi, vector& piv) { + unsigned int i; + memset(&pi, 0, sizeof(pi)); + for (i=0; i + + @@ -1772,6 +1776,10 @@ RelativePath="..\Client\pers_file_xfer.h" > + +