diff --git a/client/app.cpp b/client/app.cpp index 16bac18ffa1..ad4993371e6 100644 --- a/client/app.cpp +++ b/client/app.cpp @@ -415,7 +415,7 @@ void ACTIVE_TASK_SET::get_memory_usage() { v = &(atp->other_pids); } procinfo_app(pi, v, pm, atp->app_version->graphics_exec_file); - if (atp->app_version->is_vm_app) { + if (atp->app_version->is_vbox_app) { vbox_app_running = true; // the memory of virtual machine apps is not reported correctly, // at least on Windows. Use the VM size instead. @@ -538,12 +538,29 @@ void ACTIVE_TASK_SET::get_memory_usage() { #if defined(__linux__) || defined(_WIN32) || defined(__APPLE__) // compute non_boinc_cpu_usage - // Improved version for systems where we can get total CPU (Win, Linux, Mac) + // Improved version for systems where we can get total CPU + // (Win, Linux, Mac) // static double last_nbrc=0; double total_cpu_time_now = total_cpu_time(); - if (total_cpu_time_now != 0.0) { // total_cpu_time() returns 0.0 on error - double nbrc = total_cpu_time_now - boinc_related_cpu_time(pm, vbox_app_running); + + // total_cpu_time() returns 0.0 on error + // + if (total_cpu_time_now != 0.0) { + double brc = boinc_related_cpu_time(pm, vbox_app_running); +#ifndef _WIN32 + // on Win, boinc_related_cpu_time() includes CPU time of Docker jobs. + // On other platforms we need to do it by looking at the + // reported CPU times of the jobs + // (which may be less reliable/accurate) + // + for (ACTIVE_TASK* atp: active_tasks) { + if (atp->app_version->is_docker_app) { + brc += atp->current_cpu_time; + } + } +#endif + double nbrc = total_cpu_time_now - brc; double delta_nbrc = nbrc - last_nbrc; if (delta_nbrc < 0) delta_nbrc = 0; last_nbrc = nbrc; diff --git a/client/client_types.cpp b/client/client_types.cpp index 8f0e11bed3a..bac77d90b53 100644 --- a/client/client_types.cpp +++ b/client/client_types.cpp @@ -882,7 +882,8 @@ void APP_VERSION::init() { graphics_exec_path[0] = 0; graphics_exec_file[0] = 0; max_working_set_size = 0; - is_vm_app = false; + is_vbox_app = false; + is_docker_app = false; is_wrapper = false; index = 0; #ifdef SIM @@ -902,7 +903,10 @@ int APP_VERSION::parse(XML_PARSER& xp) { dont_throttle = true; } if (strstr(plan_class, "vbox")) { - is_vm_app = true; + is_vbox_app = true; + } + if (strstr(plan_class, "docker")) { + is_docker_app = true; } return 0; } @@ -915,9 +919,6 @@ int APP_VERSION::parse(XML_PARSER& xp) { ); return retval; } - if (strstr(file_ref.file_name, "vboxwrapper")) { - is_vm_app = true; - } app_files.push_back(file_ref); continue; } diff --git a/client/client_types.h b/client/client_types.h index f8d6f43489d..c71e354c5e9 100644 --- a/client/client_types.h +++ b/client/client_types.h @@ -372,8 +372,10 @@ struct APP_VERSION { // to use this much RAM, // so that we don't run a long sequence of jobs, // each of which turns out not to fit in available RAM - bool is_vm_app; - // currently this set if plan class includes "vbox" (kludge) + bool is_vbox_app; + // set if plan class includes "vbox" + bool is_docker_app; + // set if plan class includes "docker" bool is_wrapper; // the main program is a wrapper; run it above idle priority diff --git a/lib/procinfo.cpp b/lib/procinfo.cpp index 27b2f3f4b42..607fafb87da 100644 --- a/lib/procinfo.cpp +++ b/lib/procinfo.cpp @@ -123,9 +123,11 @@ void find_children(PROC_MAP& pm) { } } -// get resource usage of non-BOINC apps +// get resource usage of non-BOINC apps running above background priority. // NOTE: this is flawed because it doesn't account for short-lived processes. -// It's not used on Win, Mac, or Linux, which have better ways of getting total CPU usage. +// It's not used on Win, Mac, or Linux, +// which have ways of getting total CPU usage. +// See client/app.cpp // void procinfo_non_boinc(PROCINFO& procinfo, PROC_MAP& pm) { procinfo.clear(); @@ -162,8 +164,20 @@ void procinfo_non_boinc(PROCINFO& procinfo, PROC_MAP& pm) { #endif } -// get CPU time of BOINC-related processes, low-priority processes, -// and (if we're using Vbox) the Vbox daemon. +// get CPU time of things we don't want to count as non-BOINC-related +// - BOINC apps +// - low-priority processes +// - (if Vbox apps are running) the Vbox daemon +// - Windows: WSL daemon ('vmmem') +// - Linux/Mac: +// we don't account Docker/podman CPU time here, +// since we don't know what the processes are. +// Instead we do it in the client (by looking at ACTIVE_TASKS) +// +// processes named 'podman' +// +// This is subtracted from total CPU time to get +// the 'non-BOINC CPU time' used in computing preferences // double boinc_related_cpu_time(PROC_MAP& pm, bool vbox_app_running) { double sum = 0; @@ -180,8 +194,11 @@ double boinc_related_cpu_time(PROC_MAP& pm, bool vbox_app_running) { // if a VBox app is running, // count VBox processes as BOINC-related // e.g. VBoxHeadless.exe and VBoxSVC.exe on Win +#ifdef _WIN32 + || strstr(p.command, "vmmem") +#endif ) { - sum += p.user_time; + sum += (p.user_time + p.kernel_time); } } return sum; diff --git a/lib/procinfo_unix.cpp b/lib/procinfo_unix.cpp index eff43f934bd..ded0177387e 100644 --- a/lib/procinfo_unix.cpp +++ b/lib/procinfo_unix.cpp @@ -109,6 +109,9 @@ struct PROC_STAT { int parse(char*); }; +// parse a /proc//stat files (1 line) +// see https://man7.org/linux/man-pages/man5/proc_pid_stat.5.html +// int PROC_STAT::parse(char* buf) { int n = sscanf(buf, "%d (%[^)]) %c %d %d %d %d %d "