*** empty log message ***

svn path=/trunk/boinc/; revision=11107
This commit is contained in:
David Anderson 2006-09-05 19:00:59 +00:00
parent 1a99fddbd1
commit 59d5508392
11 changed files with 168 additions and 84 deletions

View File

@ -214,9 +214,7 @@ static int boinc_worker_thread_cpu_time(double& cpu) {
// communicate to the core client (via shared mem)
// the current CPU time and fraction done
//
static bool update_app_progress(
double cpu_t, double cp_cpu_t, double rss=0, double vm=0
) {
static bool update_app_progress(double cpu_t, double cp_cpu_t) {
char msg_buf[MSG_CHANNEL_SIZE], buf[256];
if (standalone) return true;
@ -235,14 +233,6 @@ static bool update_app_progress(
sprintf(buf, "<fraction_done>%2.8f</fraction_done>\n", fdone);
strcat(msg_buf, buf);
}
if (rss) {
sprintf(buf, "<rss_bytes>%f</rss_bytes>\n", rss);
strcat(msg_buf, buf);
}
if (vm) {
sprintf(buf, "<vm_bytes>%f</vm_bytes>\n", vm);
strcat(msg_buf, buf);
}
if (fpops_per_cpu_sec) {
sprintf(buf, "<fpops_per_cpu_sec>%f</fpops_per_cpu_sec>\n", fpops_per_cpu_sec);
strcat(msg_buf, buf);

View File

@ -9782,3 +9782,31 @@ David 5 Sept 2006
lib/
common_defs.h
David 5 Sept 2006
- first pass at enforcing RAM limits:
- if computer is in use (kbd/mouse input)
BOINC will use at most half of RAM
(i.e. it won't run a set of apps whose working set size
exceeds RAM/2)
_ if computer is not in use, BOINC will use at most all of RAM
(it won't run a set of apps whose WSS exceeds RAM)
This is pretty lame. For example, in case 2 BOINC will
run any set of programs, since by definitions their WSs
all fit in RAM (they may be thrashing).
So we need to do some thinking/experimenting.
- Fix HTTP bug that affects 64-bit compiles
(from Pav Lucistnik)
api/
boinc_api.C
client/
app.C,h
app_control.C
client_state.h
cpu_sched.C
cs_prefs.C
http_curl.h
html/user/
show_user.php

View File

@ -193,6 +193,47 @@ void ACTIVE_TASK_SET::free_mem() {
}
#endif
void ACTIVE_TASK_SET::get_memory_usage() {
static double last_mem_time=0;
unsigned int i;
if (gstate.now - last_mem_time < 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) {
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;
if (log_flags.mem_usage_debug) {
msg_printf(NULL, MSG_INFO,
"%s: RAM %dKB, page %dKB, user CPU %f, kernel CPU %f",
atp->result->name,
(int)(pi.working_set_size/1024), (int)(pi.swap_size/1024),
pi.user_time, pi.kernel_time
);
}
}
}
#if 0
// the following is not useful because most OSs don't
// move idle processes out of RAM, so physical memory is always full
//
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
);
#endif
}
// Do periodic checks on running apps:
// - get latest CPU time and % done info
// - check if any has exited, and clean up
@ -210,6 +251,7 @@ bool ACTIVE_TASK_SET::poll() {
send_trickle_downs();
graphics_poll();
process_control_poll();
get_memory_usage();
action |= check_rsc_limits_exceeded();
action |= get_msgs();
for (i=0; i<active_tasks.size(); i++) {
@ -225,35 +267,6 @@ bool ACTIVE_TASK_SET::poll() {
gstate.set_client_state_dirty("ACTIVE_TASK_SET::poll");
}
#if defined(_WIN32) || (defined(__GNUG__) && !defined(__APPLE__))
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
);
}
}
#endif
return action;
}
@ -477,8 +490,8 @@ 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>", x)) continue;
else if (parse_double(buf, "<rss_bytes>", x)) continue;
else if (parse_double(buf, "<vm_bytes>", vm_bytes)) continue;
else if (parse_double(buf, "<rss_bytes>", rss_bytes)) 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

@ -104,9 +104,9 @@ public:
double current_cpu_time;
// most recent CPU time reported by app
double vm_bytes;
// virtual memory used
// swap space used
double rss_bytes;
// resident set size
// 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
@ -230,6 +230,7 @@ public:
void network_available(); // notify tasks that network is available
void free_mem();
bool slot_taken(int);
void get_memory_usage();
// screensaver-related functions
ACTIVE_TASK* get_ss_app();

View File

@ -462,25 +462,6 @@ bool ACTIVE_TASK::check_max_disk_exceeded() {
return false;
}
#if 0
// if an app has exceeded its maximum allowed memory, abort it
//
bool ACTIVE_TASK::check_max_mem_exceeded() {
// TODO: calculate working set size elsewhere
if (working_set_size > max_mem_usage || working_set_size/1048576 > gstate.global_prefs.max_memory_mbytes) {
msg_printf(
result->project, MSG_INFO,
"Aborting task %s: exceeded memory limit %f\n",
result->name,
min(max_mem_usage, gstate.global_prefs.max_memory_mbytes*1048576)
);
abort_task(ERR_RSC_LIMIT_EXCEEDED, "Maximum memory usage exceeded");
return true;
}
return false;
}
#endif
bool ACTIVE_TASK::check_max_mem_exceeded() {
if (max_mem_usage != 0 && rss_bytes > max_mem_usage) {
msg_printf(
@ -887,8 +868,6 @@ bool ACTIVE_TASK::get_app_status_msg() {
}
parse_double(msg_buf, "<current_cpu_time>", current_cpu_time);
parse_double(msg_buf, "<checkpoint_cpu_time>", checkpoint_cpu_time);
parse_double(msg_buf, "<vm_bytes>", vm_bytes);
parse_double(msg_buf, "<rss_bytes>", rss_bytes);
parse_double(msg_buf, "<fpops_per_cpu_sec>", result->fpops_per_cpu_sec);
parse_double(msg_buf, "<fpops_cumulative>", result->fpops_cumulative);
parse_double(msg_buf, "<intops_per_cpu_sec>", result->intops_per_cpu_sec);

View File

@ -95,6 +95,7 @@ public:
bool started_by_screensaver;
bool exit_when_idle;
bool check_all_logins;
bool user_active; // there has been recent mouse/kbd input
bool return_results_immediately;
bool allow_remote_gui_rpc;
int cmdline_gui_rpc_port;

View File

@ -564,12 +564,31 @@ bool CLIENT_STATE::enforce_schedule() {
running_tasks.pop_back();
}
// count of how many tasks have next_scheduler_state = SCHEDULED
double mem_used = 0;
double max_mem_used;
// if user is active, use at most half of RAM;
// otherwise use all of it
//
if (gstate.user_active) {
max_mem_used = host_info.m_nbytes/2;
} else {
max_mem_used = host_info.m_nbytes;
}
if (log_flags.mem_usage_debug) {
msg_printf(0, MSG_INFO,
"enforce: max mem used %f",
max_mem_used
);
}
// keep track of how many tasks we plan on running
// (i.e. have next_scheduler_state = SCHEDULED)
//
int nrunning = running_tasks.size();
// Loop through the scheduled results
// to see if they should preempt something
// to see if they should preempt a running task
//
for (i=0; i<ordered_scheduled_results.size(); i++) {
RESULT* rp = ordered_scheduled_results[i];
@ -592,7 +611,40 @@ bool CLIENT_STATE::enforce_schedule() {
break;
}
}
if (atp) continue; // the scheduled result is already running.
if (atp) {
// the scheduled result is already running.
// see if it fits in mem
//
if (mem_used + atp->rss_bytes > max_mem_used) {
atp->next_scheduler_state = CPU_SCHED_PREEMPTED;
nrunning--;
if (log_flags.mem_usage_debug) {
msg_printf(rp->project, MSG_INFO,
"enforce: result %s mem1 %f %f %f",
rp->name, mem_used, atp->rss_bytes, max_mem_used
);
}
} else {
mem_used += atp->rss_bytes;
continue;
}
}
// if the result already has a (non-running) active task,
// see if it fits in mem
//
atp = active_tasks.lookup_result(rp);
if (atp) {
if (mem_used + atp->rss_bytes > max_mem_used) {
if (log_flags.mem_usage_debug) {
msg_printf(rp->project, MSG_INFO,
"enforce: result %s mem2 %f %f %f",
rp->name, mem_used, atp->rss_bytes, max_mem_used
);
}
continue;
}
}
// The scheduled result is not already running.
// Preempt something if needed and possible.
@ -633,6 +685,24 @@ bool CLIENT_STATE::enforce_schedule() {
atp = get_task(rp);
atp->next_scheduler_state = CPU_SCHED_SCHEDULED;
nrunning++;
mem_used += atp->rss_bytes;
}
}
// make sure we don't exceed RAM limits
//
for (i=0; i<running_tasks.size(); i++) {
atp = running_tasks[i];
if (mem_used + atp->rss_bytes > max_mem_used) {
atp->next_scheduler_state = CPU_SCHED_PREEMPTED;
if (log_flags.mem_usage_debug) {
msg_printf(atp->result->project, MSG_INFO,
"enforce: result %s mem3 %f %f %f",
atp->result->name, mem_used, atp->rss_bytes, max_mem_used
);
}
} else {
mem_used += atp->rss_bytes;
}
}

View File

@ -137,6 +137,9 @@ void CLIENT_STATE::check_suspend_activities(int& reason) {
return;
}
user_active = !host_info.users_idle(
check_all_logins, global_prefs.idle_time_to_run
);
switch(user_run_request) {
case RUN_MODE_ALWAYS: break;
case RUN_MODE_NEVER:
@ -150,11 +153,7 @@ void CLIENT_STATE::check_suspend_activities(int& reason) {
return;
}
if (!global_prefs.run_if_user_active
&& !host_info.users_idle(
check_all_logins, global_prefs.idle_time_to_run
)
) {
if (!global_prefs.run_if_user_active && user_active) {
reason = SUSPEND_REASON_USER_ACTIVE;
return;
}

View File

@ -89,8 +89,10 @@ public:
bool want_download; // at most one should be true
bool want_upload;
int connect_error; // errno from connect() (not used for anything)
int response; // HTTP status code from server
long connect_error; // errno from connect() (not used for anything)
long response; // HTTP status code from server
// the above two MUST be long (not int)
// otherwise breaks on 64-bit machines
double start_time;
double xfer_speed;
double bytes_xferred; // bytes transferred in this session

View File

@ -154,6 +154,7 @@ show_name("Tim Lan");
show_name("Egon Larsson");
show_name("Gilson Laurent");
show_name("Matt Lebofsky");
show_name("Pav Lucistnik");
show_name("Bernd Machenschalk");
show_name("Christopher Malton");
show_name("Sebastian Masch");

View File

@ -26,11 +26,11 @@ if ($format=="xml"){
start_cache(USER_PAGE_TTL, $cache_args);
db_init();
if ($auth){
$user = lookup_user_auth($auth);
$show_hosts = true;
$user = lookup_user_auth($auth);
$show_hosts = true;
} else {
$user = lookup_user_id($id);
$show_hosts = false;
$show_hosts = false;
}
if (!$user) xml_error("no such user ID");
@ -42,14 +42,14 @@ if ($format=="xml"){
$cache_args="userid=".$id;
$cached_data = get_cached_data(TOP_PAGES_TTL,$cache_args);
if ($cached_data){
// We found some old but non-stale data, let's use it
$user = unserialize($cached_data);
// We found some old but non-stale data, let's use it
$user = unserialize($cached_data);
} else {
// No data was found, generate new data for the cache and store it
db_init();
// No data was found, generate new data for the cache and store it
db_init();
$user = lookup_user_id($id);
$user = getForumPreferences($user);
set_cache_data(serialize($user),$cache_args);
$user = getForumPreferences($user);
set_cache_data(serialize($user),$cache_args);
}
if (!$user->id) error_page("No such user found - please check the ID and try again. If the user is very new it may take a while before it can be displayed.");