Page MenuHomePhorge

psutil.cc
No OneTemporary

Size
3 KB
Referenced Files
None
Subscribers
None

psutil.cc

#include "include/psutil.h"
#include <deque>
#include <chrono>
#include <thread>
#include <unordered_map>
#ifdef __APPLE__
#include <mach/mach.h>
#include <libproc.h>
#include <sys/proc_info.h>
#include <sys/sysctl.h>
#else
#include <fstream>
#include <cmath>
#include <sstream>
#include <vector>
#include <unistd.h>
#include <iostream>
#endif
struct CPUTime {
#ifdef __APPLE__
uint64_t user;
uint64_t system;
#else
unsigned long long utime;
unsigned long long stime;
unsigned long long cutime;
unsigned long long cstime;
#endif
};
int get_num_cores() {
#ifdef __APPLE__
int nm[2];
size_t len = 4;
uint32_t count;
nm[0] = CTL_HW;
nm[1] = HW_AVAILCPU;
sysctl(nm, 2, &count, &len, NULL, 0);
if (count < 1) {
nm[1] = HW_NCPU;
sysctl(nm, 2, &count, &len, NULL, 0);
}
return count > 0 ? static_cast<int>(count) : 1;
#else
return static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN));
#endif
}
CPUTime get_cpu_time(int64_t pid) {
#ifdef __APPLE__
struct proc_taskinfo pti;
int ret = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &pti, sizeof(pti));
if (ret <= 0) {
return {0, 0};
}
return {pti.pti_total_user, pti.pti_total_system};
#else
std::string stat_path = "/proc/" + std::to_string(pid) + "/stat";
std::ifstream stat_file(stat_path);
CPUTime result = {0, 0, 0, 0};
if (!stat_file.is_open()) {
std::cerr << "Failed to open " << stat_path << std::endl;
return result;
}
std::string line;
std::getline(stat_file, line);
std::istringstream iss(line);
std::string token;
std::vector<std::string> tokens;
while (std::getline(iss, token, ' ')) {
tokens.push_back(token);
}
if (tokens.size() < 17) {
std::cerr << "Unexpected format in " << stat_path << std::endl;
return result;
}
result.utime = std::stoull(tokens[13]);
result.stime = std::stoull(tokens[14]);
result.cutime = std::stoull(tokens[15]);
result.cstime = std::stoull(tokens[16]);
return result;
#endif
}
static std::unordered_map<int64_t, CPUTime> last_cpu_times;
static std::unordered_map<int64_t, double> last_cpu_percentages;
static std::deque<int64_t> insertion_order;
static const size_t max_items = 20;
void cleanup_old_entries() {
while (last_cpu_times.size() > max_items) {
int64_t oldest_pid = insertion_order.front();
insertion_order.pop_front();
last_cpu_times.erase(oldest_pid);
last_cpu_percentages.erase(oldest_pid);
}
}
double get_process_cpu_usage_percentage(int64_t pid) {
const std::chrono::milliseconds measurement_interval(200);
static int num_cores = get_num_cores();
CPUTime start_time = get_cpu_time(pid);
auto start = std::chrono::steady_clock::now();
std::this_thread::sleep_for(measurement_interval);
CPUTime end_time = get_cpu_time(pid);
auto end = std::chrono::steady_clock::now();
double elapsed_seconds = std::chrono::duration<double>(end - start).count();
if (last_cpu_times.find(pid) == last_cpu_times.end()) {
last_cpu_times[pid] = start_time;
last_cpu_percentages[pid] = 0.0;
insertion_order.push_back(pid);
cleanup_old_entries();
return 0.0;
}
CPUTime& last_time = last_cpu_times[pid];
#ifdef __APPLE__
uint64_t user_ticks = end_time.user - last_time.user;
uint64_t system_ticks = end_time.system - last_time.system;
uint64_t total_ticks = user_ticks + system_ticks;
double seconds = static_cast<double>(total_ticks) / 1e7;
double cpu_usage = (seconds / elapsed_seconds) * 100.0;
#else
unsigned long long total_time =
(end_time.utime + end_time.stime + end_time.cutime + end_time.cstime) -
(last_time.utime + last_time.stime + last_time.cutime + last_time.cstime);
double seconds = static_cast<double>(total_time) / sysconf(_SC_CLK_TCK);
double cpu_usage = 100.0 * (seconds / elapsed_seconds) / num_cores;
#endif
last_cpu_times[pid] = end_time;
double& last_percentage = last_cpu_percentages[pid];
cpu_usage = (cpu_usage * 0.3) + (last_percentage * 0.2);
last_percentage = cpu_usage;
cleanup_old_entries();
return std::min(cpu_usage, 100.0 * num_cores);
}

File Metadata

Mime Type
text/x-c
Expires
Wed, May 7, 2:53 AM (2 d)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
86376
Default Alt Text
psutil.cc (3 KB)

Event Timeline