Implement CPU usage monitoring functions
This commit is contained in:
parent
df3623b478
commit
0781d86a2b
@ -93,3 +93,101 @@ char *os_get_config_path(const char *name)
|
||||
dstr_cat(&path, name);
|
||||
return path.array;
|
||||
}
|
||||
|
||||
struct os_cpu_usage_info {
|
||||
int64_t last_cpu_time;
|
||||
int64_t last_sys_time;
|
||||
int core_count;
|
||||
};
|
||||
|
||||
static inline void convert_time_value(struct timeval *dst, time_value_t *src)
|
||||
{
|
||||
dst->tv_sec = src->seconds;
|
||||
dst->tv_usec = src->microseconds;
|
||||
}
|
||||
|
||||
static inline void add_time_value(time_value_t *dst, time_value_t *a,
|
||||
time_value_t *b)
|
||||
{
|
||||
dst->microseconds = a->microseconds + b->microseconds;
|
||||
dst->seconds = a->seconds + b->seconds;
|
||||
|
||||
if (dst->microseconds >= 1000000) {
|
||||
dst->seconds += dst->microseconds / 1000000;
|
||||
dst->microseconds %= 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_time_info(int64_t *cpu_time, int64_t *sys_time)
|
||||
{
|
||||
mach_port_t task = mach_task_self();
|
||||
struct task_thread_times_info thread_data;
|
||||
struct task_basic_info_64 task_data;
|
||||
mach_msg_type_number_t count;
|
||||
kern_return_t kern_ret;
|
||||
time_value_t cur_time;
|
||||
|
||||
*cpu_time = 0;
|
||||
*sys_time = 0;
|
||||
|
||||
count = TASK_THREAD_TIMES_INFO_COUNT;
|
||||
kern_ret = task_info(task, TASK_THREAD_TIMES_INFO,
|
||||
(task_info_t)&thread_data, &count);
|
||||
if (kern_ret != KERN_SUCCESS)
|
||||
return false;
|
||||
|
||||
count = TASK_BASIC_INFO_64_COUNT;
|
||||
kern_ret = task_info(task, TASK_BASIC_INFO_64,
|
||||
(task_info_t)&task_data, &count);
|
||||
if (kern_ret != KERN_SUCCESS)
|
||||
return false;
|
||||
|
||||
add_time_value(&cur_time, &thread_data.user_time,
|
||||
&thread_data.system_time);
|
||||
add_time_value(&cur_time, &cur_time, &task_data.user_time);
|
||||
add_time_value(&cur_time, &cur_time, &task_data.system_time);
|
||||
|
||||
*cpu_time = os_gettime_ns() / 1000;
|
||||
*sys_time = cur_time.seconds * 1000000 + cur_time.microseconds;
|
||||
return true;
|
||||
}
|
||||
|
||||
os_cpu_usage_info_t os_cpu_usage_info_start(void)
|
||||
{
|
||||
struct os_cpu_usage_info *info = bmalloc(sizeof(*info));
|
||||
|
||||
if (!get_time_info(&info->last_cpu_time, &info->last_sys_time)) {
|
||||
bfree(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info->core_count = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
return info;
|
||||
}
|
||||
|
||||
double os_cpu_usage_info_query(os_cpu_usage_info_t info)
|
||||
{
|
||||
int64_t sys_time, cpu_time;
|
||||
int64_t sys_time_delta, cpu_time_delta;
|
||||
|
||||
if (!info || !get_time_info(&cpu_time, &sys_time))
|
||||
return 0.0;
|
||||
|
||||
sys_time_delta = sys_time - info->last_sys_time;
|
||||
cpu_time_delta = cpu_time - info->last_cpu_time;
|
||||
|
||||
if (cpu_time_delta == 0)
|
||||
return 0.0;
|
||||
|
||||
info->last_sys_time = sys_time;
|
||||
info->last_cpu_time = cpu_time;
|
||||
|
||||
return (double)sys_time_delta * 100.0 / (double)cpu_time_delta /
|
||||
(double)info->core_count;
|
||||
}
|
||||
|
||||
void os_cpu_usage_info_destroy(os_cpu_usage_info_t info)
|
||||
{
|
||||
if (info)
|
||||
bfree(info);
|
||||
}
|
||||
|
@ -23,6 +23,11 @@
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
#include <sys/times.h>
|
||||
#include <sys/vtimes.h>
|
||||
#endif
|
||||
|
||||
#include "dstr.h"
|
||||
#include "platform.h"
|
||||
|
||||
@ -56,6 +61,60 @@ void os_dlclose(void *module)
|
||||
dlclose(module);
|
||||
}
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
|
||||
struct os_cpu_usage_info {
|
||||
clock_t last_cpu_time, last_sys_time, last_user_time;
|
||||
int core_count;
|
||||
};
|
||||
|
||||
os_cpu_usage_info_t os_cpu_usage_info_start(void)
|
||||
{
|
||||
struct os_cpu_usage_info *info = bmalloc(sizeof(*info));
|
||||
struct tms time_sample;
|
||||
|
||||
info->last_cpu_time = times(&time_sample);
|
||||
info->last_sys_time = time_sample.tms_stime;
|
||||
info->last_user_time = time_sample.tms_utime;
|
||||
info->core_count = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
return info;
|
||||
}
|
||||
|
||||
double os_cpu_usage_info_query(os_cpu_usage_info_t info)
|
||||
{
|
||||
struct tms time_sample;
|
||||
clock_t cur_cpu_time;
|
||||
double percent;
|
||||
|
||||
if (!info)
|
||||
return 0.0;
|
||||
|
||||
cur_cpu_time = times(&time_sample);
|
||||
if (cur_cpu_time <= info->last_cpu_time ||
|
||||
time_sample.tms_stime < info->last_sys_time ||
|
||||
time_sample.tms_utime < info->last_user_time)
|
||||
return 0.0;
|
||||
|
||||
percent = (double)(time_sample.tms_stime - info->last_sys_time +
|
||||
(time_sample.tms_utime - info->last_user_time));
|
||||
percent /= (double)(cur_cpu_time - info->last_cpu_time);
|
||||
percent /= (double)info->core_count;
|
||||
|
||||
info->last_cpu_time = cur_cpu_time;
|
||||
info->last_sys_time = time_sample.tms_stime;
|
||||
info->last_user_time = time_sample.tms_utime;
|
||||
|
||||
return percent * 100.0;
|
||||
}
|
||||
|
||||
void os_cpu_usage_info_destroy(os_cpu_usage_info_t info)
|
||||
{
|
||||
if (info)
|
||||
bfree(info);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool os_sleepto_ns(uint64_t time_target)
|
||||
{
|
||||
uint64_t current = os_gettime_ns();
|
||||
|
@ -86,6 +86,62 @@ void os_dlclose(void *module)
|
||||
FreeLibrary(module);
|
||||
}
|
||||
|
||||
union time_data {
|
||||
FILETIME ft;
|
||||
unsigned long long val;
|
||||
};
|
||||
|
||||
struct os_cpu_usage_info {
|
||||
union time_data last_time, last_sys_time, last_user_time;
|
||||
DWORD core_count;
|
||||
};
|
||||
|
||||
os_cpu_usage_info_t os_cpu_usage_info_start(void)
|
||||
{
|
||||
struct os_cpu_usage_info *info = bzalloc(sizeof(*info));
|
||||
SYSTEM_INFO si;
|
||||
FILETIME dummy;
|
||||
|
||||
GetSystemInfo(&si);
|
||||
GetSystemTimeAsFileTime(&info->last_time.ft);
|
||||
GetProcessTimes(GetCurrentProcess(), &dummy, &dummy,
|
||||
&info->last_sys_time.ft, &info->last_user_time.ft);
|
||||
info->core_count = si.dwNumberOfProcessors;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
double os_cpu_usage_info_query(os_cpu_usage_info_t info)
|
||||
{
|
||||
union time_data cur_time, cur_sys_time, cur_user_time;
|
||||
FILETIME dummy;
|
||||
double percent;
|
||||
|
||||
if (!info)
|
||||
return 0.0;
|
||||
|
||||
GetSystemTimeAsFileTime(&cur_time.ft);
|
||||
GetProcessTimes(GetCurrentProcess(), &dummy, &dummy,
|
||||
&cur_sys_time.ft, &cur_user_time.ft);
|
||||
|
||||
percent = (double)(cur_sys_time.val - info->last_sys_time.val +
|
||||
(cur_user_time.val - info->last_user_time.val));
|
||||
percent /= (double)(cur_time.val - info->last_time.val);
|
||||
percent /= (double)info->core_count;
|
||||
|
||||
info->last_time.val = cur_time.val;
|
||||
info->last_sys_time.val = cur_sys_time.val;
|
||||
info->last_user_time.val = cur_user_time.val;
|
||||
|
||||
return percent * 100.0;
|
||||
}
|
||||
|
||||
void os_cpu_usage_info_destroy(os_cpu_usage_info_t info)
|
||||
{
|
||||
if (info)
|
||||
bfree(info);
|
||||
}
|
||||
|
||||
bool os_sleepto_ns(uint64_t time_target)
|
||||
{
|
||||
uint64_t t = os_gettime_ns();
|
||||
|
@ -69,6 +69,13 @@ EXPORT void *os_dlopen(const char *path);
|
||||
EXPORT void *os_dlsym(void *module, const char *func);
|
||||
EXPORT void os_dlclose(void *module);
|
||||
|
||||
struct os_cpu_usage_info;
|
||||
typedef struct os_cpu_usage_info *os_cpu_usage_info_t;
|
||||
|
||||
EXPORT os_cpu_usage_info_t os_cpu_usage_info_start(void);
|
||||
EXPORT double os_cpu_usage_info_query(os_cpu_usage_info_t info);
|
||||
EXPORT void os_cpu_usage_info_destroy(os_cpu_usage_info_t info);
|
||||
|
||||
/**
|
||||
* Sleeps to a specific time (in nanoseconds). Doesn't have to be super
|
||||
* accurate in terms of actual slept time because the target time is ensured.
|
||||
|
Loading…
x
Reference in New Issue
Block a user