mirror of https://github.com/BOINC/boinc.git
parent
5b3b61df8c
commit
6ae2249607
|
@ -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
|
||||
|
|
33
client/app.C
33
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; 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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&);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue