memory usage

svn path=/trunk/boinc/; revision=11020
This commit is contained in:
David Anderson 2006-08-28 18:22:07 +00:00
parent 5b3b61df8c
commit 6ae2249607
7 changed files with 147 additions and 15 deletions

View File

@ -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 <mem_usage_debug/> 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

View File

@ -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; i<active_tasks.size(); i++) {
for (i=0; i<active_tasks.size(); i++) {
ACTIVE_TASK* atp = active_tasks[i];
if (atp->task_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<PROCINFO> piv;
PROCINFO pi;
procinfo_setup(piv);
for (i=0; i<active_tasks.size(); i++) {
ACTIVE_TASK* atp = active_tasks[i];
if (atp->task_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;
}

View File

@ -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

View File

@ -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&);

View File

@ -1,10 +1,20 @@
#include <vector>
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<PROCINFO>& pi).
extern int procinfo_setup(std::vector<PROCINFO>&);
// call this first to get data structure
extern void procinfo_app(PROCINFO&, std::vector<PROCINFO>&);
// call this to get mem usage for a given app
// (marks process as BOINC)
extern void procinfo_other(PROCINFO&, std::vector<PROCINFO>&);
// After getting mem usage for all BOINC apps,
// call this to get mem usage for everything else

View File

@ -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<PROCINFO>& 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<PROCINFO>& 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<PROCINFO>& pi) {
if (pBuffer) HeapFree(GetProcessHeap(), NULL, pBuffer);
return 0;
}
int get_procinfo_NT(vector<PROCINFO>& pi) {
int get_procinfo_NT(vector<PROCINFO>&) {
return 0;
}
int get_procinfo_9X(vector<PROCINFO>& pi) {
int get_procinfo_9X(vector<PROCINFO>&) {
return 0;
}
int get_procinfo(vector<PROCINFO>& pi) {
// get a list of all running processes.
//
int procinfo_setup(vector<PROCINFO>& pi) {
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(osvi);
GetVersionEx(&osvi);
@ -83,7 +102,7 @@ int get_procinfo(vector<PROCINFO>& 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<PROCINFO>& 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<PROCINFO>& piv, int pid, int start) {
unsigned int i;
for (i=start; i<piv.size(); i++) {
PROCINFO& p = piv[i];
if (p.id == pid || p.parentid == pid) {
pi.kernel_time += p.kernel_time;
pi.user_time += p.user_time;
pi.swap_size += p.swap_size;
pi.working_set_size += p.working_set_size;
p.is_boinc_app = true;
}
if (p.parentid == pid) {
add_proc_totals(pi, piv, p.id, i+1); // recursion - woo hoo!
}
}
}
// fill in the given PROCINFO (which initially is zero except for id)
// with totals from that process and all its descendants
//
void procinfo_app(PROCINFO& pi, vector<PROCINFO>& piv) {
add_proc_totals(pi, piv, pi.id, 0);
}
void procinfo_other(PROCINFO& pi, vector<PROCINFO>& piv) {
unsigned int i;
memset(&pi, 0, sizeof(pi));
for (i=0; i<piv.size(); i++) {
PROCINFO& p = piv[i];
if (!p.is_boinc_app) {
pi.kernel_time += p.kernel_time;
pi.user_time += p.user_time;
pi.swap_size += p.swap_size;
pi.working_set_size += p.working_set_size;
p.is_boinc_app = true;
}
}
}

View File

@ -1511,6 +1511,10 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\lib\procinfo_win.C"
>
</File>
<File
RelativePath="..\Client\scheduler_op.C"
>
@ -1772,6 +1776,10 @@
RelativePath="..\Client\pers_file_xfer.h"
>
</File>
<File
RelativePath="..\lib\procinfo.h"
>
</File>
<File
RelativePath="..\client\scheduler_op.h"
>