Skip to content

Commit 122d135

Browse files
committed
feat: gpustack add cpu utilization for mac/linux
1 parent 7353a7d commit 122d135

File tree

5 files changed

+147
-29
lines changed

5 files changed

+147
-29
lines changed

src/detection/cpu/cpu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "fastfetch.h"
44

55
#define FF_CPU_TEMP_UNSET (0/0.0)
6+
#define FF_CPU_UTILIZATION_RATE_UNSET -1
67

78
typedef struct FFCPUCore
89
{
@@ -18,6 +19,7 @@ typedef struct FFCPUResult
1819
uint16_t coresPhysical;
1920
uint16_t coresLogical;
2021
uint16_t coresOnline;
22+
double coresUtilizationRate;
2123

2224
double frequencyBase; // GHz
2325
double frequencyMax; // GHz

src/detection/cpu/cpu_apple.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
#include "detection/temps/temps_apple.h"
44
#include "util/stringUtils.h"
55

6+
#include <stdlib.h>
7+
#include <sys/types.h>
8+
#include <sys/sysctl.h>
9+
#include <mach/mach.h>
10+
#include <mach/processor_info.h>
11+
#include <mach/mach_host.h>
12+
#include <unistd.h>
13+
614
static double detectCpuTemp(const FFstrbuf* cpuName)
715
{
816
double result = 0;
@@ -99,6 +107,49 @@ static const char* detectCoreCount(FFCPUResult* cpu)
99107
return NULL;
100108
}
101109

110+
static double detectCoreUtilizationRate()
111+
{
112+
double cpuUsage = FF_CPU_UTILIZATION_RATE_UNSET;
113+
114+
natural_t cpuCount;
115+
processor_info_array_t cpuInfo;
116+
processor_info_array_t prevCpuInfo = NULL;
117+
mach_msg_type_number_t numCPUInfo;
118+
mach_msg_type_number_t numPrevCpuInfo = 0;
119+
host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &cpuCount, (processor_info_array_t *)&cpuInfo, &numCPUInfo);
120+
121+
sleep(1);
122+
123+
prevCpuInfo = cpuInfo;
124+
numPrevCpuInfo = numCPUInfo;
125+
host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &cpuCount, (processor_info_array_t *)&cpuInfo, &numCPUInfo);
126+
127+
float totalInUse = 0, totalTotal = 0;
128+
for (unsigned i = 0; i < cpuCount; i++)
129+
{
130+
float userTime = cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_USER] - prevCpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_USER];
131+
float systemTime = cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM] - prevCpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM];
132+
float niceTime = cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE] - prevCpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE];
133+
float idleTime = cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE] - prevCpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE];
134+
135+
float inUse = userTime + systemTime + niceTime;
136+
float total = inUse + idleTime;
137+
138+
totalInUse += inUse;
139+
totalTotal += total;
140+
}
141+
142+
cpuUsage = (totalInUse / totalTotal) * 100;
143+
144+
if (prevCpuInfo)
145+
vm_deallocate(mach_task_self(), (vm_address_t)prevCpuInfo, numPrevCpuInfo * sizeof(integer_t));
146+
147+
if (cpuInfo)
148+
vm_deallocate(mach_task_self(), (vm_address_t)cpuInfo, numCPUInfo * sizeof(integer_t));
149+
150+
return cpuUsage;
151+
}
152+
102153
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
103154
{
104155
if (ffSysctlGetString("machdep.cpu.brand_string", &cpu->name) != NULL)
@@ -125,5 +176,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
125176

126177
cpu->temperature = options->temp ? detectCpuTemp(&cpu->name) : FF_CPU_TEMP_UNSET;
127178

179+
cpu->coresUtilizationRate = detectCoreUtilizationRate();
180+
128181
return NULL;
129182
}

src/detection/cpu/cpu_linux.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,58 @@ static double detectCPUTemp(void)
210210
return FF_CPU_TEMP_UNSET;
211211
}
212212

213+
typedef struct
214+
{
215+
unsigned long long user;
216+
unsigned long long nice;
217+
unsigned long long system;
218+
unsigned long long idle;
219+
unsigned long long iowait;
220+
unsigned long long irq;
221+
unsigned long long softirq;
222+
unsigned long long steal;
223+
unsigned long long guest;
224+
unsigned long long guest_nice;
225+
} CPUUsage;
226+
227+
static void readCPUUsage(CPUUsage *usage)
228+
{
229+
FF_AUTO_CLOSE_FILE FILE *cpustat = fopen("/proc/stat", "r");
230+
if (cpustat != NULL)
231+
{
232+
char buffer[256];
233+
if (fgets(buffer, sizeof(buffer), cpustat) != NULL)
234+
{
235+
sscanf(buffer, "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu", &usage->user, &usage->nice, &usage->system,&usage->idle, &usage->iowait, &usage->irq,&usage->softirq, &usage->steal, &usage->guest,&usage->guest_nice);
236+
}
237+
}
238+
}
239+
240+
static double detectCPUUtilizationRate(void)
241+
{
242+
CPUUsage prev, curr;
243+
readCPUUsage(&prev);
244+
245+
sleep(1);
246+
247+
readCPUUsage(&curr);
248+
249+
unsigned long long prev_idle = prev.idle + prev.iowait;
250+
unsigned long long curr_idle = curr.idle + curr.iowait;
251+
252+
unsigned long long prev_non_idle = prev.user + prev.nice + prev.system + prev.irq + prev.softirq + prev.steal;
253+
unsigned long long curr_non_idle = curr.user + curr.nice + curr.system + curr.irq + curr.softirq + curr.steal;
254+
255+
unsigned long long prev_total = prev_idle + prev_non_idle;
256+
unsigned long long curr_total = curr_idle + curr_non_idle;
257+
258+
unsigned long long totald = curr_total - prev_total;
259+
unsigned long long idled = curr_idle - prev_idle;
260+
261+
double cpu_percentage = ((double)(totald - idled) / (double)totald) * 100.0;
262+
return cpu_percentage;
263+
}
264+
213265
static void parseIsa(FFstrbuf* cpuIsa)
214266
{
215267
if(ffStrbufStartsWithS(cpuIsa, "rv"))
@@ -271,6 +323,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
271323
cpu->coresLogical = (uint16_t) get_nprocs_conf();
272324
cpu->coresOnline = (uint16_t) get_nprocs();
273325
cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, cpu->coresLogical);
326+
cpu->coresUtilizationRate = detectCPUUtilizationRate();
274327

275328
if (!detectFrequency(cpu, options) || cpu->frequencyBase != cpu->frequencyBase)
276329
cpu->frequencyBase = ffStrbufToDouble(&cpuMHz) / 1000;

src/modules/cpu/cpu.c

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include "modules/cpu/cpu.h"
77
#include "util/stringUtils.h"
88

9-
#define FF_CPU_NUM_FORMAT_ARGS 10
9+
#define FF_CPU_NUM_FORMAT_ARGS 11
1010

1111
static int sortCores(const FFCPUCore* a, const FFCPUCore* b)
1212
{
@@ -17,13 +17,13 @@ void ffPrintCPU(FFCPUOptions* options)
1717
{
1818
FFCPUResult cpu = {
1919
.temperature = FF_CPU_TEMP_UNSET,
20-
.frequencyMin = 0.0/0.0,
21-
.frequencyMax = 0.0/0.0,
22-
.frequencyBase = 0.0/0.0,
23-
.frequencyBiosLimit = 0.0/0.0,
20+
.frequencyMin = 0.0 / 0.0,
21+
.frequencyMax = 0.0 / 0.0,
22+
.frequencyBase = 0.0 / 0.0,
23+
.frequencyBiosLimit = 0.0 / 0.0,
2424
.name = ffStrbufCreate(),
2525
.vendor = ffStrbufCreate(),
26-
};
26+
.coresUtilizationRate = FF_CPU_UTILIZATION_RATE_UNSET};
2727

2828
const char* error = ffDetectCPU(options, &cpu);
2929

@@ -86,6 +86,12 @@ void ffPrintCPU(FFCPUOptions* options)
8686
ffTempsAppendNum(cpu.temperature, &str, options->tempConfig, &options->moduleArgs);
8787
}
8888

89+
if (cpu.coresUtilizationRate != FF_CPU_UTILIZATION_RATE_UNSET)
90+
{
91+
ffStrbufAppendS(&str, " - ");
92+
ffPercentAppendNum(&str, cpu.coresUtilizationRate, options->percent, true, &options->moduleArgs);
93+
}
94+
8995
ffStrbufPutTo(&str, stdout);
9096
}
9197
else
@@ -107,17 +113,18 @@ void ffPrintCPU(FFCPUOptions* options)
107113
FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate();
108114
ffTempsAppendNum(cpu.temperature, &tempStr, options->tempConfig, &options->moduleArgs);
109115
FF_PRINT_FORMAT_CHECKED(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_CPU_NUM_FORMAT_ARGS, ((FFformatarg[]){
110-
{FF_FORMAT_ARG_TYPE_STRBUF, &cpu.name, "name"},
111-
{FF_FORMAT_ARG_TYPE_STRBUF, &cpu.vendor, "vendor"},
112-
{FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresPhysical, "cores-physical"},
113-
{FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresLogical, "cores-logical"},
114-
{FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresOnline, "cores-online"},
115-
{FF_FORMAT_ARG_TYPE_STRING, freqBase, "freq-base"},
116-
{FF_FORMAT_ARG_TYPE_STRING, freqMax, "freq-max"},
117-
{FF_FORMAT_ARG_TYPE_STRBUF, &tempStr, "temperature"},
118-
{FF_FORMAT_ARG_TYPE_STRBUF, &coreTypes, "core-types"},
119-
{FF_FORMAT_ARG_TYPE_STRING, freqBioslimit, "freq-bios-limit"},
120-
}));
116+
{FF_FORMAT_ARG_TYPE_STRBUF, &cpu.name, "name"},
117+
{FF_FORMAT_ARG_TYPE_STRBUF, &cpu.vendor, "vendor"},
118+
{FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresPhysical, "cores-physical"},
119+
{FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresLogical, "cores-logical"},
120+
{FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresOnline, "cores-online"},
121+
{FF_FORMAT_ARG_TYPE_DOUBLE, &cpu.coresUtilizationRate, "cores-utilization-rate"},
122+
{FF_FORMAT_ARG_TYPE_STRING, freqBase, "freq-base"},
123+
{FF_FORMAT_ARG_TYPE_STRING, freqMax, "freq-max"},
124+
{FF_FORMAT_ARG_TYPE_STRBUF, &tempStr, "temperature"},
125+
{FF_FORMAT_ARG_TYPE_STRBUF, &coreTypes, "core-types"},
126+
{FF_FORMAT_ARG_TYPE_STRING, freqBioslimit, "freq-bios-limit"},
127+
}));
121128
}
122129
}
123130

@@ -230,6 +237,7 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_
230237
yyjson_mut_obj_add_uint(doc, cores, "physical", cpu.coresPhysical);
231238
yyjson_mut_obj_add_uint(doc, cores, "logical", cpu.coresLogical);
232239
yyjson_mut_obj_add_uint(doc, cores, "online", cpu.coresOnline);
240+
yyjson_mut_obj_add_real(doc, cores, "utilizationRate", cpu.coresUtilizationRate);
233241

234242
yyjson_mut_val* frequency = yyjson_mut_obj_add_obj(doc, obj, "frequency");
235243
yyjson_mut_obj_add_real(doc, frequency, "base", cpu.frequencyBase);
@@ -254,18 +262,19 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_
254262

255263
void ffPrintCPUHelpFormat(void)
256264
{
257-
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_CPU_MODULE_NAME, "{1} ({5}) @ {7} GHz", FF_CPU_NUM_FORMAT_ARGS, ((const char* []) {
258-
"Name - name",
259-
"Vendor - vendor",
260-
"Physical core count - cores-physical",
261-
"Logical core count - cores-logical",
262-
"Online core count - cores-online",
263-
"Base frequency - freq-base",
264-
"Max frequency - freq-max",
265-
"Temperature (formatted) - temperature",
266-
"Logical core count grouped by frequency - core-types",
267-
"Bios limited frequency - freq-bios-limit",
268-
}));
265+
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_CPU_MODULE_NAME, "{1} ({5}) @ {7} GHz", FF_CPU_NUM_FORMAT_ARGS, ((const char *[]){
266+
"Name - name",
267+
"Vendor - vendor",
268+
"Physical core count - cores-physical",
269+
"Logical core count - cores-logical",
270+
"Online core count - cores-online",
271+
"Utilization rate - cores-utilization-rate",
272+
"Base frequency - freq-base",
273+
"Max frequency - freq-max",
274+
"Temperature (formatted) - temperature",
275+
"Logical core count grouped by frequency - core-types",
276+
"Bios limited frequency - freq-bios-limit",
277+
}));
269278
}
270279

271280
void ffInitCPUOptions(FFCPUOptions* options)

src/modules/cpu/option.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ typedef struct FFCPUOptions
1313
FFColorRangeConfig tempConfig;
1414
uint8_t freqNdigits;
1515
bool showPeCoreCount;
16+
FFColorRangeConfig percent;
1617
} FFCPUOptions;

0 commit comments

Comments
 (0)