*** empty log message ***

svn path=/trunk/boinc/; revision=11124
This commit is contained in:
David Anderson 2006-09-08 19:27:42 +00:00
parent db24601537
commit 14a7fb85f6
8 changed files with 100 additions and 30 deletions

View File

@ -9957,3 +9957,36 @@ David 7 Sept 2006
client/
*.C
David 8 Sept 2006
- core client: frustrating attempt to get page fault rate on Windows.
It turns out that the "page fault count" reported by Windows
includes "soft" page faults that don't read from disk.
A typical process gets hundreds or thousands of these per second.
There doesn't seem to be a way to get a count
of real page faults.
In any case: I added PROCINFO to the ACTIVE_TASK structure,
eliminating the need for the vm_nbytes and rss_bytes fields.
Note: the reason I'm worrying about this is:
suppose an OS defines a process's "working set"
as the amount of RAM it currently has.
Then all running apps will appear to fit in RAM,
and our goal of avoiding thrashing will fail.
I was looking at page fault rate as a way to get around this.
However: I ran across a note that says that Windows
defines "working set" as "the amount of memory needed
for the process to run efficiently".
If that's the case, we don't need to worry about page fault rate.
client/
app.C,h
app_control.C
cpu_sched.C
lib/
procinfo.h
procinfo_win.C
win_build/
boinc_cli_curl.vcproj

View File

@ -95,12 +95,11 @@ ACTIVE_TASK::ACTIVE_TASK() {
checkpoint_cpu_time = 0;
checkpoint_wall_time = 0;
current_cpu_time = 0;
vm_bytes = 0;
rss_bytes = 0;
have_trickle_down = false;
send_upload_file_status = false;
pending_suspend_via_quit = false;
want_network = 0;
memset(&procinfo, 0, sizeof(procinfo));
#ifdef _WIN32
pid_handle = 0;
thread_handle = 0;
@ -197,25 +196,28 @@ void ACTIVE_TASK_SET::get_memory_usage() {
static double last_mem_time=0;
unsigned int i;
if (gstate.now - last_mem_time < 10) return;
double diff = gstate.now - last_mem_time;
if (diff < 10) return;
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) {
PROCINFO& pi = atp->procinfo;
unsigned long last_page_fault_count = pi.page_fault_count;
memset(&pi, 0, sizeof(pi));
pi.id = atp->pid;
procinfo_app(pi, piv);
atp->rss_bytes = pi.working_set_size;
atp->vm_bytes = pi.swap_size;
int pf = pi.page_fault_count - last_page_fault_count;
pi.page_fault_rate = pf/diff;
if (log_flags.mem_usage_debug) {
msg_printf(NULL, MSG_INFO,
"[mem_usage_debug] %s: RAM %dKB, page %dKB, user CPU %f, kernel CPU %f",
"[mem_usage_debug] %s: RAM %dKB, page %dKB, %f page faults/sec, user CPU %f, kernel CPU %f",
atp->result->name,
(int)(pi.working_set_size/1024), (int)(pi.swap_size/1024),
pi.page_fault_rate,
pi.user_time, pi.kernel_time
);
}
@ -387,8 +389,9 @@ int ACTIVE_TASK::write(MIOFILE& fout) {
" <checkpoint_cpu_time>%f</checkpoint_cpu_time>\n"
" <fraction_done>%f</fraction_done>\n"
" <current_cpu_time>%f</current_cpu_time>\n"
" <vm_bytes>%f</vm_bytes>\n"
" <rss_bytes>%f</rss_bytes>\n",
" <swap_size>%f</swap_size>\n"
" <working_set_size>%f</working_set_size>\n"
" <page_fault_rate>%f</page_fault_rate>\n",
result->project->master_url,
result->name,
task_state,
@ -398,8 +401,9 @@ int ACTIVE_TASK::write(MIOFILE& fout) {
checkpoint_cpu_time,
fraction_done,
current_cpu_time,
vm_bytes,
rss_bytes
procinfo.swap_size,
procinfo.working_set_size,
procinfo.page_fault_rate
);
if (supports_graphics() && !gstate.disable_graphics) {
fout.printf(
@ -489,8 +493,9 @@ int ACTIVE_TASK::parse(MIOFILE& fin) {
else if (parse_double(buf, "<fraction_done>", fraction_done)) continue;
else if (parse_double(buf, "<current_cpu_time>", current_cpu_time)) continue;
else if (parse_int(buf, "<active_task_state>", n)) continue;
else if (parse_double(buf, "<vm_bytes>", vm_bytes)) continue;
else if (parse_double(buf, "<rss_bytes>", rss_bytes)) continue;
else if (parse_double(buf, "<swap_size>", procinfo.swap_size)) continue;
else if (parse_double(buf, "<working_set_size>", procinfo.working_set_size)) continue;
else if (parse_double(buf, "<page_fault_rate>", procinfo.page_fault_rate)) continue;
else if (match_tag(buf, "<supports_graphics/>")) continue;
else if (parse_int(buf, "<graphics_mode_acked>", n)) continue;
else if (parse_int(buf, "<scheduler_state>", n)) continue;

View File

@ -27,6 +27,7 @@
#include "client_types.h"
#include "app_ipc.h"
#include "procinfo.h"
class CLIENT_STATE;
typedef int PROCESS_ID;
@ -82,7 +83,9 @@ public:
WORKUNIT* wup;
APP_VERSION* app_version;
PROCESS_ID pid;
int slot; // which slot (determines directory)
PROCINFO procinfo;
int slot; // subdirectory of slots/ where this runs
int task_state;
int scheduler_state;
int next_scheduler_state; // temp
@ -103,10 +106,6 @@ public:
// wall time at the last checkpoint
double current_cpu_time;
// most recent CPU time reported by app
double vm_bytes;
// swap space used
double rss_bytes;
// working set size
int current_disk_usage(double&);
// disk used by output files and temp files of this task
char slot_dir[256]; // directory where process runs

View File

@ -468,12 +468,12 @@ bool ACTIVE_TASK::check_max_disk_exceeded() {
}
bool ACTIVE_TASK::check_max_mem_exceeded() {
if (max_mem_usage != 0 && rss_bytes > max_mem_usage) {
if (max_mem_usage != 0 && procinfo.working_set_size > max_mem_usage) {
if (log_flags.mem_usage_debug) {
msg_printf(
result->project, MSG_INFO,
"[mem_usage_debug] Task %s: memory usage %f exceeds limit %f\n",
result->name, rss_bytes, max_mem_usage
result->name, procinfo.working_set_size, max_mem_usage
);
}
//abort_task(ERR_RSC_LIMIT_EXCEEDED, "Maximum memory usage exceeded");
@ -490,7 +490,7 @@ bool ACTIVE_TASK_SET::vm_limit_exceeded(double vm_limit) {
for (i=0; i<active_tasks.size(); ++i) {
atp = active_tasks[i];
if (!atp->process_exists()) continue;
total_vm_usage += atp->vm_bytes;
total_vm_usage += atp->procinfo.swap_size;
}
return (total_vm_usage > vm_limit);

View File

@ -615,17 +615,17 @@ bool CLIENT_STATE::enforce_schedule() {
// the scheduled result is already running.
// see if it fits in mem
//
if (mem_used + atp->rss_bytes > max_mem_used) {
if (mem_used + atp->procinfo.working_set_size > max_mem_used) {
atp->next_scheduler_state = CPU_SCHED_PREEMPTED;
nrunning--;
if (log_flags.mem_usage_debug) {
msg_printf(rp->project, MSG_INFO,
"[mem_usage_debug] enforce: result %s mem1 %f %f %f",
rp->name, mem_used, atp->rss_bytes, max_mem_used
rp->name, mem_used, atp->procinfo.working_set_size, max_mem_used
);
}
} else {
mem_used += atp->rss_bytes;
mem_used += atp->procinfo.working_set_size;
continue;
}
}
@ -635,11 +635,11 @@ bool CLIENT_STATE::enforce_schedule() {
//
atp = active_tasks.lookup_result(rp);
if (atp) {
if (mem_used + atp->rss_bytes > max_mem_used) {
if (mem_used + atp->procinfo.working_set_size > max_mem_used) {
if (log_flags.mem_usage_debug) {
msg_printf(rp->project, MSG_INFO,
"[mem_usage_debug] enforce: result %s mem2 %f %f %f",
rp->name, mem_used, atp->rss_bytes, max_mem_used
rp->name, mem_used, atp->procinfo.working_set_size, max_mem_used
);
}
continue;
@ -685,7 +685,7 @@ bool CLIENT_STATE::enforce_schedule() {
atp = get_task(rp);
atp->next_scheduler_state = CPU_SCHED_SCHEDULED;
nrunning++;
mem_used += atp->rss_bytes;
mem_used += atp->procinfo.working_set_size;
}
}
@ -693,16 +693,16 @@ bool CLIENT_STATE::enforce_schedule() {
//
for (i=0; i<running_tasks.size(); i++) {
atp = running_tasks[i];
if (mem_used + atp->rss_bytes > max_mem_used) {
if (mem_used + atp->procinfo.working_set_size > max_mem_used) {
atp->next_scheduler_state = CPU_SCHED_PREEMPTED;
if (log_flags.mem_usage_debug) {
msg_printf(atp->result->project, MSG_INFO,
"[mem_usage_debug] enforce: result %s mem3 %f %f %f",
atp->result->name, mem_used, atp->rss_bytes, max_mem_used
atp->result->name, mem_used, atp->procinfo.working_set_size, max_mem_used
);
}
} else {
mem_used += atp->rss_bytes;
mem_used += atp->procinfo.working_set_size;
}
}

View File

@ -1,3 +1,25 @@
// Berkeley Open Infrastructure for Network Computing
// http://boinc.berkeley.edu
// Copyright (C) 2005 University of California
//
// This is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any later version.
//
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// To view the GNU Lesser General Public License visit
// http://www.gnu.org/copyleft/lesser.html
// or write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#ifndef _PROCINFO_
#define _PROCINFO_
#include <vector>
struct PROCINFO {
@ -5,9 +27,12 @@ struct PROCINFO {
int parentid;
double swap_size;
double working_set_size;
unsigned long page_fault_count;
double user_time;
double kernel_time;
bool is_boinc_app;
double page_fault_rate; // derived by higher-level code
};
extern int procinfo_setup(std::vector<PROCINFO>&);
@ -18,3 +43,5 @@ extern void procinfo_app(PROCINFO&, std::vector<PROCINFO>&);
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
#endif

View File

@ -67,6 +67,7 @@ int get_procinfo_XP(vector<PROCINFO>& pi) {
p.parentid = pProcesses->InheritedFromProcessId;
p.swap_size = pProcesses->VmCounters.PagefileUsage;
p.working_set_size = pProcesses->VmCounters.WorkingSetSize;
p.page_fault_count = pProcesses->VmCounters.PageFaultCount;
p.user_time = ((double) pProcesses->UserTime.QuadPart)/1e7;
p.kernel_time = ((double) pProcesses->KernelTime.QuadPart)/1e7;
p.id = pProcesses->ProcessId;
@ -137,6 +138,7 @@ void add_proc_totals(PROCINFO& pi, vector<PROCINFO>& piv, int pid, int start) {
pi.user_time += p.user_time;
pi.swap_size += p.swap_size;
pi.working_set_size += p.working_set_size;
pi.page_fault_count += p.page_fault_count;
p.is_boinc_app = true;
}
if (p.parentid == pid) {

View File

@ -1724,6 +1724,10 @@
RelativePath="..\client\dhrystone.h"
>
</File>
<File
RelativePath="..\lib\diagnostics_win.h"
>
</File>
<File
RelativePath="..\lib\error_numbers.h"
>