Skip to content

Commit

Permalink
fix: add cpu usage (#1868)
Browse files Browse the repository at this point in the history
Co-authored-by: vansangpfiev <[email protected]>
  • Loading branch information
vansangpfiev and sangjanai authored Jan 17, 2025
1 parent e4e3e90 commit 193946e
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 7 deletions.
5 changes: 3 additions & 2 deletions engine/cli/commands/hardware_list_cmd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ bool HardwareListCmd::Exec(const std::string& host, int port,
if (!ho.has_value() || ho.value().show_cpu) {
std::cout << "CPU Information:" << std::endl;
Table table;
std::vector<std::string> column_headers{"#", "Arch", "Cores", "Model",
"Instructions"};
std::vector<std::string> column_headers{"#", "Arch", "Cores",
"Model", "Usage", "Instructions"};

Row_t header{column_headers.begin(), column_headers.end()};
table.add_row(header);
Expand All @@ -52,6 +52,7 @@ bool HardwareListCmd::Exec(const std::string& host, int port,
row.emplace_back(cpu.arch);
row.emplace_back(std::to_string(cpu.cores));
row.emplace_back(cpu.model);
row.emplace_back(std::to_string(cpu.usage));
std::string insts;
for (auto const& i : cpu.instructions) {
insts += i + " ";
Expand Down
15 changes: 10 additions & 5 deletions engine/common/hardware_common.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#pragma once
#include <assert.h>
#include <json/json.h>
#include <string>
#include <variant>
#include <vector>
#include <assert.h>

namespace cortex::hw {

Expand All @@ -26,6 +26,7 @@ struct CPU {
int cores;
std::string arch;
std::string model;
float usage;
std::vector<std::string> instructions;
};

Expand All @@ -34,6 +35,7 @@ inline Json::Value ToJson(const CPU& cpu) {
res["arch"] = cpu.arch;
res["cores"] = cpu.cores;
res["model"] = cpu.model;
res["usage"] = cpu.usage;
Json::Value insts(Json::arrayValue);
for (auto const& i : cpu.instructions) {
insts.append(i);
Expand All @@ -47,11 +49,16 @@ inline CPU FromJson(const Json::Value& root) {
int cores = root["cores"].asInt();
std::string arch = root["arch"].asString();
std::string model = root["model"].asString();
float usage = root["usage"].asFloat();
std::vector<std::string> insts;
for (auto const& i : root["instructions"]) {
insts.emplace_back(i.asString());
}
return {.cores = cores, .arch = arch, .model = model, .instructions = insts};
return {.cores = cores,
.arch = arch,
.model = model,
.usage = usage,
.instructions = insts};
}
} // namespace cpu

Expand Down Expand Up @@ -143,7 +150,6 @@ inline OS FromJson(const Json::Value& root) {
}
} // namespace os


struct PowerInfo {
std::string charging_status;
int battery_life;
Expand All @@ -166,7 +172,6 @@ inline PowerInfo FromJson(const Json::Value& root) {
}
} // namespace power


namespace {
int64_t ByteToMiB(int64_t b) {
return b / 1024 / 1024;
Expand Down Expand Up @@ -215,4 +220,4 @@ inline StorageInfo FromJson(const Json::Value& root) {
.available = root["available"].asInt64()};
}
} // namespace storage
}
} // namespace cortex::hw
4 changes: 4 additions & 0 deletions engine/utils/hardware/cpu_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <string_view>
#include <vector>
#include "common/hardware_common.h"
#include "cpu_usage.h"
#include "hwinfo/hwinfo.h"
#include "utils/cpuid/cpu_info.h"

Expand All @@ -15,9 +16,12 @@ inline CPU GetCPUInfo() {
return CPU{};
auto cpu = res[0];
cortex::cpuid::CpuInfo inst;
float usage = GetCPUUsage();
// float usage = 0;
return CPU{.cores = cpu.numPhysicalCores(),
.arch = std::string(GetArch()),
.model = cpu.modelName(),
.usage = usage,
.instructions = inst.instructions()};
}
} // namespace cortex::hw
162 changes: 162 additions & 0 deletions engine/utils/hardware/cpu_usage.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#pragma once
#include <chrono>
#include <iostream>
#include <sstream>
#include <thread>
#include <vector>

#ifdef _WIN32
#include <pdh.h>
#include <windows.h>
#pragma comment(lib, "pdh.lib")
#elif defined(__APPLE__) || defined(__MACH__)
#include <mach/mach_host.h>
#include <mach/mach_init.h>
#else
#include <unistd.h>
#include <fstream>
#endif
#include "utils/logging_utils.h"

namespace cortex::hw {
inline double GetCPUUsage() {
#if defined(_WIN32)
unsigned long long previous_total_ticks = 0;
unsigned long long previous_idle_ticks = 0;

auto calculate_cpu_load = [&](unsigned long long idle_ticks,
unsigned long long total_ticks) {
unsigned long long total_ticks_since_last_time =
total_ticks - previous_total_ticks;
unsigned long long idle_ticks_since_last_time =
idle_ticks - previous_idle_ticks;

float ret = 1.0f - ((total_ticks_since_last_time > 0)
? ((float)idle_ticks_since_last_time) /
total_ticks_since_last_time
: 0);

previous_total_ticks = total_ticks;
previous_idle_ticks = idle_ticks;
return ret * 100;
};

auto file_time_to_int64 = [](const FILETIME& ft) {
return (((unsigned long long)(ft.dwHighDateTime)) << 32) |
((unsigned long long)ft.dwLowDateTime);
};

FILETIME idle_time, kernel_time, user_time;
float res = 0;
constexpr const int kCount = 100;
for (int i = 0; i < kCount; i++) {
res += GetSystemTimes(&idle_time, &kernel_time, &user_time)
? calculate_cpu_load(file_time_to_int64(idle_time),
file_time_to_int64(kernel_time) +
file_time_to_int64(user_time))
: -1.0f;
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
return res < 0 ? -1.0f : res / kCount;

#elif defined(__APPLE__) || defined(__MACH__)
// macOS implementation
host_cpu_load_info_data_t cpu_info;
mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;

static unsigned long long previous_total_ticks = 0;
static unsigned long long previous_idle_ticks = 0;

if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO,
(host_info_t)&cpu_info, &count) == KERN_SUCCESS) {
unsigned long long total_ticks = 0;
for (int i = 0; i < CPU_STATE_MAX; i++) {
total_ticks += cpu_info.cpu_ticks[i];
}

unsigned long long idle_ticks = cpu_info.cpu_ticks[CPU_STATE_IDLE];

unsigned long long total_ticks_since_last_time =
total_ticks - previous_total_ticks;
unsigned long long idle_ticks_since_last_time =
idle_ticks - previous_idle_ticks;

double cpu_usage = 1.0f - ((double)idle_ticks_since_last_time /
total_ticks_since_last_time);

previous_total_ticks = total_ticks;
previous_idle_ticks = idle_ticks;

return cpu_usage * 100.0;
}
return -1.0;

#else
// Linux implementation
std::vector<unsigned long long> last_total_user, last_total_user_low,
last_total_sys, last_total_idle;

std::vector<unsigned long long> total_user, total_user_low, total_sys,
total_idle;

std::ifstream stat_file("/proc/stat");
if (stat_file.is_open()) {
std::string line;
int cpu_count = 0;
double total_cpu_percentage = 0.0;

while (std::getline(stat_file, line)) {
if (line.substr(0, 3) != "cpu")
break; // We only want lines that start with "cpu"

cpu_count++;
std::vector<unsigned long long> values;
std::istringstream iss(line);
std::string cpu;
iss >> cpu;
unsigned long long value;
while (iss >> value) {
values.push_back(value);
}

if (values.size() < 4)
continue;

total_user.push_back(values[0]);
total_user_low.push_back(values[1]);
total_sys.push_back(values[2]);
total_idle.push_back(values[3]);

if (last_total_user.size() < cpu_count) {
last_total_user.push_back(0);
last_total_user_low.push_back(0);
last_total_sys.push_back(0);
last_total_idle.push_back(0);
}

unsigned long long total =
(total_user[cpu_count - 1] - last_total_user[cpu_count - 1]) +
(total_user_low[cpu_count - 1] - last_total_user_low[cpu_count - 1]) +
(total_sys[cpu_count - 1] - last_total_sys[cpu_count - 1]);
double percent = total;
total += (total_idle[cpu_count - 1] - last_total_idle[cpu_count - 1]);
percent /= total;
percent *= 100;

total_cpu_percentage += percent;

last_total_user[cpu_count - 1] = total_user[cpu_count - 1];
last_total_user_low[cpu_count - 1] = total_user_low[cpu_count - 1];
last_total_sys[cpu_count - 1] = total_sys[cpu_count - 1];
last_total_idle[cpu_count - 1] = total_idle[cpu_count - 1];
}
stat_file.close();

if (cpu_count > 0) {
return total_cpu_percentage / cpu_count; // Return average CPU usage
}
}
return -1.0;
#endif
}
} // namespace cortex::hw

0 comments on commit 193946e

Please sign in to comment.