提交 0781d86a 编写于 作者: J jp9000

Implement CPU usage monitoring functions

上级 df3623b4
......@@ -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.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册