mirror of https://github.com/BOINC/boinc.git
Merge pull request #4875 from BOINC/mac_get_total_cpu_usage
Mac: compute non-BOINC CPU usage in a more accurate way
This commit is contained in:
commit
c0c58151bc
|
@ -1,6 +1,6 @@
|
|||
// This file is part of BOINC.
|
||||
// http://boinc.berkeley.edu
|
||||
// Copyright (C) 2008 University of California
|
||||
// Copyright (C) 2022 University of California
|
||||
//
|
||||
// BOINC is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License
|
||||
|
@ -486,51 +486,55 @@ void ACTIVE_TASK_SET::get_memory_usage() {
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(__linux__) || defined(_WIN32)
|
||||
#if defined(__linux__) || defined(_WIN32) || defined(__APPLE__)
|
||||
// compute non_boinc_cpu_usage
|
||||
// Improved version for systems where we can get total CPU (Win, Linux)
|
||||
// Improved version for systems where we can get total CPU (Win, Linux, Mac)
|
||||
//
|
||||
static double last_nbrc=0;
|
||||
double nbrc = total_cpu_time() - boinc_related_cpu_time(pm, using_vbox);
|
||||
double delta_nbrc = nbrc - last_nbrc;
|
||||
if (delta_nbrc < 0) delta_nbrc = 0;
|
||||
last_nbrc = nbrc;
|
||||
if (!first) {
|
||||
non_boinc_cpu_usage = delta_nbrc/(diff*gstate.host_info.p_ncpus);
|
||||
//printf("non_boinc_cpu_usage %f\n", non_boinc_cpu_usage);
|
||||
}
|
||||
#else
|
||||
// compute non_boinc_cpu_usage
|
||||
//
|
||||
// NOTE: this is flawed because it doesn't count short-lived processes
|
||||
// correctly. Linux and Win use a better approach (see above).
|
||||
//
|
||||
// mem usage info is not useful because most OSs don't
|
||||
// move idle processes out of RAM, so physical memory is always full.
|
||||
// Also (at least on Win) page faults are used for various things,
|
||||
// not all of them generate disk I/O,
|
||||
// so they're not useful for detecting paging/thrashing.
|
||||
//
|
||||
static double last_cpu_time;
|
||||
PROCINFO pi;
|
||||
procinfo_non_boinc(pi, pm);
|
||||
if (log_flags.mem_usage_debug) {
|
||||
//procinfo_show(pm);
|
||||
msg_printf(NULL, MSG_INFO,
|
||||
"[mem_usage] All others: WS %.2fMB, swap %.2fMB, user %.3fs, kernel %.3fs",
|
||||
pi.working_set_size/MEGA, pi.swap_size/MEGA,
|
||||
pi.user_time, pi.kernel_time
|
||||
);
|
||||
}
|
||||
double new_cpu_time = pi.user_time + pi.kernel_time;
|
||||
if (!first) {
|
||||
non_boinc_cpu_usage = (new_cpu_time - last_cpu_time)/(diff*gstate.host_info.p_ncpus);
|
||||
// processes might have exited in the last 10 sec,
|
||||
// causing this to be negative.
|
||||
if (non_boinc_cpu_usage < 0) non_boinc_cpu_usage = 0;
|
||||
}
|
||||
last_cpu_time = new_cpu_time;
|
||||
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, using_vbox);
|
||||
double delta_nbrc = nbrc - last_nbrc;
|
||||
if (delta_nbrc < 0) delta_nbrc = 0;
|
||||
last_nbrc = nbrc;
|
||||
if (!first) {
|
||||
non_boinc_cpu_usage = delta_nbrc/(diff*gstate.host_info.p_ncpus);
|
||||
//printf("non_boinc_cpu_usage %f\n", non_boinc_cpu_usage);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// compute non_boinc_cpu_usage the old way
|
||||
//
|
||||
// NOTE: this is flawed because it doesn't count short-lived processes
|
||||
// correctly. Linux and Win use a better approach (see above).
|
||||
//
|
||||
// mem usage info is not useful because most OSs don't
|
||||
// move idle processes out of RAM, so physical memory is always full.
|
||||
// Also (at least on Win) page faults are used for various things,
|
||||
// not all of them generate disk I/O,
|
||||
// so they're not useful for detecting paging/thrashing.
|
||||
//
|
||||
static double last_cpu_time;
|
||||
PROCINFO pi;
|
||||
procinfo_non_boinc(pi, pm);
|
||||
if (log_flags.mem_usage_debug) {
|
||||
//procinfo_show(pm);
|
||||
msg_printf(NULL, MSG_INFO,
|
||||
"[mem_usage] All others: WS %.2fMB, swap %.2fMB, user %.3fs, kernel %.3fs",
|
||||
pi.working_set_size/MEGA, pi.swap_size/MEGA,
|
||||
pi.user_time, pi.kernel_time
|
||||
);
|
||||
}
|
||||
double new_cpu_time = pi.user_time + pi.kernel_time;
|
||||
if (!first) {
|
||||
non_boinc_cpu_usage = (new_cpu_time - last_cpu_time)/(diff*gstate.host_info.p_ncpus);
|
||||
// processes might have exited in the last 10 sec,
|
||||
// causing this to be negative.
|
||||
if (non_boinc_cpu_usage < 0) non_boinc_cpu_usage = 0;
|
||||
}
|
||||
last_cpu_time = new_cpu_time;
|
||||
}
|
||||
|
||||
if (!first) {
|
||||
if (log_flags.mem_usage_debug) {
|
||||
|
@ -542,7 +546,7 @@ void ACTIVE_TASK_SET::get_memory_usage() {
|
|||
first = false;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // ! defined (SIM)
|
||||
|
||||
// There's a new trickle file.
|
||||
// Move it from slot dir to project dir
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// This file is part of BOINC.
|
||||
// http://boinc.berkeley.edu
|
||||
// Copyright (C) 2020 University of California
|
||||
// Copyright (C) 2022 University of California
|
||||
//
|
||||
// BOINC is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License
|
||||
|
@ -26,6 +26,8 @@
|
|||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <locale.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <mach/mach.h>
|
||||
|
||||
#if SHOW_TIMING
|
||||
#include <Carbon/Carbon.h>
|
||||
|
@ -167,3 +169,44 @@ int procinfo_setup(PROC_MAP& pm) {
|
|||
setlocale(LC_ALL, old_locale.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get total user-mode CPU time
|
||||
//
|
||||
// From usr/include/mach/processor_info.h:
|
||||
// struct processor_cpu_load_info { /* number of ticks while running... */
|
||||
// unsigned int cpu_ticks[CPU_STATE_MAX]; /* ... in the given mode */
|
||||
// };
|
||||
//
|
||||
double total_cpu_time() {
|
||||
static bool first = true;
|
||||
natural_t processorCount = 0;
|
||||
processor_cpu_load_info_t cpuLoad;
|
||||
mach_msg_type_number_t processorMsgCount;
|
||||
static double scale;
|
||||
uint64_t totalUserTime = 0;
|
||||
|
||||
if (first) {
|
||||
first = false;
|
||||
long hz = sysconf(_SC_CLK_TCK);
|
||||
scale = 1./hz;
|
||||
}
|
||||
|
||||
kern_return_t err = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &processorCount, (processor_info_array_t *)&cpuLoad, &processorMsgCount);
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
for (natural_t i = 0; i < processorCount; i++) {
|
||||
// Calc user and nice CPU usage, with guards against 32-bit overflow
|
||||
// (values are natural_t)
|
||||
uint64_t user = 0, nice = 0;
|
||||
|
||||
user = cpuLoad[i].cpu_ticks[CPU_STATE_USER];
|
||||
nice = cpuLoad[i].cpu_ticks[CPU_STATE_NICE];
|
||||
|
||||
totalUserTime = totalUserTime + user + nice;
|
||||
}
|
||||
|
||||
return totalUserTime * scale;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// This file is part of BOINC.
|
||||
// http://boinc.berkeley.edu
|
||||
// Copyright (C) 2008 University of California
|
||||
// Copyright (C) 2022 University of California
|
||||
//
|
||||
// BOINC is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License
|
||||
|
|
Loading…
Reference in New Issue