mirror of https://github.com/BOINC/boinc.git
*** empty log message ***
svn path=/trunk/boinc/; revision=11124
This commit is contained in:
parent
db24601537
commit
14a7fb85f6
|
@ -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
|
||||
|
|
31
client/app.C
31
client/app.C
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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) {
|
||||
|
|
|
@ -1724,6 +1724,10 @@
|
|||
RelativePath="..\client\dhrystone.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\lib\diagnostics_win.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\lib\error_numbers.h"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue