base/system/cpu/private/linux_impl/cpu_profile.cpp¶
CPU Profile Information Query Implementation (Linux) More...
Functions¶
| Name | |
|---|---|
| cf::expected< cf::CPUProfileInfo, cf::CPUProfileInfoError > | query_cpu_profile_info() Internal Windows Query for CPU profile information. |
Detailed Description¶
CPU Profile Information Query Implementation (Linux)
Author: Charliechen114514 (chengh1922@mails.jlu.edu.cn)
Version: 0.1
Date: 2026-02-22
Copyright: Copyright © 2026
Functions Documentation¶
function query_cpu_profile_info¶
Internal Windows Query for CPU profile information.
Return: cf::expected
Source code¶
#include "cpu_profile.h"
#include "base/linux/proc_parser.h"
#include <cstdio>
#include <fstream>
#include <string_view>
#include <thread>
#include <unistd.h>
namespace {
// Configurable CPU usage sampling delay (milliseconds)
constexpr int CPU_USAGE_SAMPLE_DELAY_MS = 100;
// Read CPU frequency from sysfs file (kHz to Hz conversion)
uint32_t readCpuFreq(const char* path) noexcept {
if (auto freq_khz = cf::read_uint32_file(path)) {
return *freq_khz * 1000; // Convert kHz to Hz
}
return 0;
}
// Returns CPU usage percentage (0-100)
// Note: This function blocks for CPU_USAGE_SAMPLE_DELAY_MS milliseconds
float getCpuUsage() noexcept {
FILE* stat = fopen("/proc/stat", "r");
if (!stat) {
return 0.0f;
}
// Parse first line: "cpu user nice system idle iowait irq softirq"
uint64_t user1 = 0, nice1 = 0, system1 = 0, idle1 = 0, iowait1 = 0, irq1 = 0, softirq1 = 0;
if (fscanf(stat, "cpu %lu %lu %lu %lu %lu %lu %lu", &user1, &nice1, &system1, &idle1, &iowait1,
&irq1, &softirq1) != 7) {
fclose(stat);
return 0.0f;
}
fclose(stat);
const uint64_t idleTotal1 = idle1 + iowait1;
const uint64_t total1 = user1 + nice1 + system1 + idle1 + iowait1 + irq1 + softirq1;
// Sleep briefly to get delta
std::this_thread::sleep_for(std::chrono::milliseconds(CPU_USAGE_SAMPLE_DELAY_MS));
// Re-read
stat = fopen("/proc/stat", "r");
if (!stat) {
return 0.0f;
}
uint64_t user2 = 0, nice2 = 0, system2 = 0, idle2 = 0, iowait2 = 0, irq2 = 0, softirq2 = 0;
if (fscanf(stat, "cpu %lu %lu %lu %lu %lu %lu %lu", &user2, &nice2, &system2, &idle2, &iowait2,
&irq2, &softirq2) != 7) {
fclose(stat);
return 0.0f;
}
fclose(stat);
const uint64_t idleTotal2 = idle2 + iowait2;
const uint64_t total2 = user2 + nice2 + system2 + idle2 + iowait2 + irq2 + softirq2;
const uint64_t totalDelta = total2 - total1;
const uint64_t idleDelta = idleTotal2 - idleTotal1;
if (totalDelta == 0) {
return 0.0f;
}
return 100.0f * (1.0f - static_cast<float>(idleDelta) / static_cast<float>(totalDelta));
}
} // namespace
cf::expected<cf::CPUProfileInfo, cf::CPUProfileInfoError> query_cpu_profile_info() {
cf::CPUProfileInfo profile_info{};
// Get logical and physical core counts from /proc/cpuinfo
std::ifstream cpuinfo("/proc/cpuinfo");
if (cpuinfo.is_open()) {
std::string line;
int logicalCount = 0;
int physicalCount = 0;
bool foundPhysicalCores = false;
while (std::getline(cpuinfo, line)) {
const std::string_view line_sv(line);
// Count "processor" entries for logical cores
if (line_sv.find("processor") == 0) {
const std::string_view numStr = cf::parse_cpuinfo_field(line_sv, "processor");
if (!numStr.empty()) {
if (auto num = cf::parse_uint32(numStr)) {
logicalCount = static_cast<int>(*num) + 1;
}
}
}
// Get "cpu cores" for physical cores (same for all cores, read first occurrence)
if (!foundPhysicalCores) {
const std::string_view coresStr = cf::parse_cpuinfo_field(line_sv, "cpu cores");
if (!coresStr.empty()) {
if (auto cores = cf::parse_uint32(coresStr)) {
physicalCount = static_cast<int>(*cores);
foundPhysicalCores = true;
}
}
}
}
// Fallback: if physical cores not found, use logical count
if (physicalCount == 0) {
physicalCount = logicalCount;
}
// Also try sysconf for logical count as fallback
if (logicalCount == 0) {
logicalCount = sysconf(_SC_NPROCESSORS_ONLN);
if (logicalCount < 0) {
logicalCount = 1;
}
}
profile_info.logical_cnt = static_cast<uint16_t>(logicalCount);
profile_info.physical_cnt = static_cast<uint16_t>(physicalCount);
} else {
// Fallback to sysconf
int logicalCount = sysconf(_SC_NPROCESSORS_ONLN);
if (logicalCount < 0) {
logicalCount = 1;
}
profile_info.logical_cnt = static_cast<uint16_t>(logicalCount);
profile_info.physical_cnt = static_cast<uint16_t>(logicalCount);
}
// Get frequency from cpufreq sysfs
profile_info.current_frequecy =
readCpuFreq("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq");
profile_info.max_frequency =
readCpuFreq("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq");
// If cpufreq is not available, try cpuinfo_max_freq
if (profile_info.max_frequency == 0) {
profile_info.max_frequency =
readCpuFreq("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq");
}
// Get CPU usage
profile_info.cpu_usage_percentage = getCpuUsage();
return profile_info;
}
Updated on 2026-03-09 at 10:14:01 +0000