diff options
| author | ruki <[email protected]> | 2022-07-29 10:58:29 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-07-29 10:58:29 +0800 |
| commit | d554a535538a83a4b071e4113ad96afe7bd9a694 (patch) | |
| tree | ffdd35c1bfa291cc29f2a7296406d5b7ff85b505 | |
| parent | e60aa2dd105a14da59e1fedbcdbf3bc4adb7ba36 (diff) | |
| parent | 4fc14288cfe6b2ecd0164ffb1b4dd4669adbd72d (diff) | |
Merge pull request #2613 from xmake-io/cpuinfo
add cpuinfo
| -rw-r--r-- | .github/workflows/freebsd.yml | 2 | ||||
| -rw-r--r-- | core/src/xmake/os/cpuinfo.c | 203 | ||||
| -rw-r--r-- | core/src/xmake/os/meminfo.c | 1 | ||||
| -rw-r--r-- | tests/modules/os/cpuinfo.lua | 7 | ||||
| -rw-r--r-- | tests/modules/os/meminfo.lua | 6 | ||||
| -rw-r--r-- | xmake/core/base/cpu.lua | 30 | ||||
| -rw-r--r-- | xmake/core/base/memory.lua | 8 |
7 files changed, 253 insertions, 4 deletions
diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml index 0cd61b130..805c5266a 100644 --- a/.github/workflows/freebsd.yml +++ b/.github/workflows/freebsd.yml @@ -20,7 +20,7 @@ jobs: submodules: true - name: Tests - uses: vmactions/[email protected] + uses: vmactions/freebsd-vm@v0 with: usesh: true mem: 4096 diff --git a/core/src/xmake/os/cpuinfo.c b/core/src/xmake/os/cpuinfo.c index bec9aff2c..49f6e27a4 100644 --- a/core/src/xmake/os/cpuinfo.c +++ b/core/src/xmake/os/cpuinfo.c @@ -29,6 +29,201 @@ * includes */ #include "prefix.h" +#if defined(TB_CONFIG_OS_MACOSX) +# include <sys/sysctl.h> +# include <sys/types.h> +# include <mach/mach.h> +# include <mach/processor_info.h> +# include <mach/mach_host.h> +#elif defined(TB_CONFIG_OS_WINDOWS) +# include <windows.h> +#elif defined(TB_CONFIG_OS_LINUX) +# include <stdio.h> +#elif defined(TB_CONFIG_OS_BSD) +# include <stdio.h> +# include <string.h> +# include <sys/types.h> +# include <sys/sysctl.h> +# include <unistd.h> +#endif + +/* ////////////////////////////////////////////////////////////////////////////////////// + * private implementation + */ +#if defined(TB_CONFIG_OS_WINDOWS) +static tb_uint64_t xm_os_cpuinfo_subtract_times(FILETIME const* one, FILETIME const* two) +{ + LARGE_INTEGER a, b; + a.LowPart = one->dwLowDateTime; + a.HighPart = one->dwHighDateTime; + + b.LowPart = two->dwLowDateTime; + b.HighPart = two->dwHighDateTime; + + return (tb_uint64_t)(a.QuadPart - b.QuadPart); +} +#endif + +static tb_float_t xm_os_cpuinfo_usagerate() +{ +#if defined(TB_CONFIG_OS_MACOSX) + tb_float_t usagerate = 0; + natural_t cpu_count = 0; + processor_info_array_t cpuinfo; + mach_msg_type_number_t cpuinfo_count; + static tb_hong_t s_time = 0; + if (tb_mclock() - s_time > 1000 && host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &cpu_count, &cpuinfo, &cpuinfo_count) == KERN_SUCCESS) + { + static processor_info_array_t s_cpuinfo_prev = tb_null; + static mach_msg_type_number_t s_cpuinfo_count_prev = 0; + for (tb_int_t i = 0; i < cpu_count; ++i) + { + tb_int_t use, total; + if (s_cpuinfo_prev) + { + use = (cpuinfo[(CPU_STATE_MAX * i) + CPU_STATE_USER] - s_cpuinfo_prev[(CPU_STATE_MAX * i) + CPU_STATE_USER]) + + (cpuinfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM] - s_cpuinfo_prev[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM]) + + (cpuinfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE] - s_cpuinfo_prev[(CPU_STATE_MAX * i) + CPU_STATE_NICE]); + total = use + (cpuinfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE] - s_cpuinfo_prev[(CPU_STATE_MAX * i) + CPU_STATE_IDLE]); + } + else + { + use = cpuinfo[(CPU_STATE_MAX * i) + CPU_STATE_USER] + cpuinfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM] + cpuinfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE]; + total = use + cpuinfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE]; + } + usagerate += total > 0? ((tb_float_t)use / (tb_float_t)total) : 0; + } + if (s_cpuinfo_prev) + vm_deallocate(mach_task_self(), (vm_address_t)s_cpuinfo_prev, sizeof(integer_t) * s_cpuinfo_count_prev); + s_time = tb_mclock(); + s_cpuinfo_prev = cpuinfo; + s_cpuinfo_count_prev = cpuinfo_count; + } + return cpu_count > 0? usagerate / cpu_count : 0; +#elif defined(TB_CONFIG_OS_WINDOWS) + // kernel include idle_time + tb_float_t usagerate = 0; + FILETIME idle, kernel, user; + if (GetSystemTimes(&idle, &kernel, &user)) + { + static FILETIME idle_prev = {0}; + static FILETIME kernel_prev = {0}; + static FILETIME user_prev = {0}; + + if (idle_prev.dwLowDateTime != 0 && idle_prev.dwHighDateTime != 0) + { + tb_uint64_t idle_diff = xm_os_cpuinfo_subtract_times(&idle, &idle_prev); + tb_uint64_t kernel_diff = xm_os_cpuinfo_subtract_times(&kernel, &kernel_prev); + tb_uint64_t user_diff = xm_os_cpuinfo_subtract_times(&user, &user_prev); + + // kernel_time - idle_time = kernel_time, because kernel include idle_time + tb_uint64_t sys_total = kernel_diff + user_diff; + tb_uint64_t kernel_total = kernel_diff - idle_diff; + + // sometimes kernel_time > idle_time + if (sys_total > 0) + usagerate = (tb_float_t)((tb_double_t)(kernel_total + user_diff) / sys_total); + } + + idle_prev = idle; + kernel_prev = kernel; + user_prev = user; + } + return usagerate; +#elif defined(TB_CONFIG_OS_LINUX) + tb_float_t usagerate = 0; + if (tb_file_info("/proc/stat", tb_null)) + { + tb_bool_t ok = tb_false; + FILE* fp = fopen("/proc/stat", "r"); + if (fp) + { + tb_char_t line[8192]; + static tb_int64_t total_prev = 0; + static tb_int64_t active_prev = 0; + while (!feof(fp)) + { + /* cpu 548760 0 867417 102226682 12430 0 9089 0 0 0 + * cpu0 136863 0 218110 25632388 2706 0 2328 0 0 0 + * cpu1 148383 0 213941 25627686 3925 0 2129 0 0 0 + * + * The meanings of the columns are as follows, from left to right: + * + * user: normal processes executing in user mode + * nice: niced processes executing in user mode + * system: processes executing in kernel mode + * idle: twiddling thumbs + * iowait: waiting for I/O to complete + * irq: servicing interrupts + * softirq: servicing softirqs + * steal + * guest + * guest_nice + */ + if (fgets(line, sizeof(line), fp) && !tb_strncmp(line, "cpu ", 4)) + { + tb_int64_t user, nice, sys, idle, iowait, irq, softirq, steal, guest, guest_nice; + if (10 == sscanf(line, "cpu %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld", + &user, &nice, &sys, &idle, &iowait, &irq, &softirq, &steal, &guest, &guest_nice)) + { + tb_int64_t active = user + nice + sys + irq + softirq + steal + guest + guest_nice; + tb_int64_t total = user + nice + sys + idle + iowait + irq + softirq + steal + guest + guest_nice; + if (total_prev > 0 && active_prev > 0) + { + tb_int64_t total_diff = total - total_prev; + tb_int64_t active_diff = active - active_prev; + if (total_diff > 0) + usagerate = (tb_float_t)((tb_double_t)active_diff / total_diff); + } + total_prev = total; + active_prev = active; + } + break; + } + } + fclose(fp); + } + } + return usagerate; +#elif defined(TB_CONFIG_OS_BSD) +# define CP_USER 0 +# define CP_NICE 1 +# define CP_SYS 2 +# define CP_INTR 3 +# define CP_IDLE 4 +# define CPUSTATES 5 + + static tb_int64_t total_prev = 0; + static tb_int64_t active_prev = 0; + + tb_float_t usagerate = 0; + long states[CPUSTATES] = {0}; + size_t states_size = sizeof(states); + if (sysctlbyname("kern.cp_time", &states, &states_size, tb_null, 0) == 0) + { + tb_long_t user = states[CP_USER]; + tb_long_t nice = states[CP_NICE]; + tb_long_t sys = states[CP_SYS]; + tb_long_t intr = states[CP_INTR]; + tb_long_t idle = states[CP_IDLE]; + + tb_int64_t active = user + nice + sys + intr; + tb_int64_t total = user + nice + sys + idle + intr; + if (total_prev > 0 && active_prev > 0) + { + tb_int64_t total_diff = total - total_prev; + tb_int64_t active_diff = active - active_prev; + if (total_diff > 0) + usagerate = (tb_float_t)((tb_double_t)active_diff / total_diff); + } + total_prev = total; + active_prev = active; + } + return usagerate; +#else + return 0; +#endif +} /* ////////////////////////////////////////////////////////////////////////////////////// * implementation @@ -54,5 +249,13 @@ tb_int_t xm_os_cpuinfo(lua_State* lua) lua_pushinteger(lua, ncpu > 0? ncpu : 1); lua_settable(lua, -3); + // get cpu usage rate + tb_float_t usagerate = xm_os_cpuinfo_usagerate(); + if (usagerate >= 0) + { + lua_pushstring(lua, "usagerate"); + lua_pushnumber(lua, usagerate); + lua_settable(lua, -3); + } return 1; } diff --git a/core/src/xmake/os/meminfo.c b/core/src/xmake/os/meminfo.c index b679e5aee..cd9ace234 100644 --- a/core/src/xmake/os/meminfo.c +++ b/core/src/xmake/os/meminfo.c @@ -36,6 +36,7 @@ # include <mach-o/dyld.h> # include <mach-o/nlist.h> #elif defined(TB_CONFIG_OS_LINUX) +# include <stdio.h> # include <sys/sysinfo.h> #elif defined(TB_CONFIG_OS_WINDOWS) # include <windows.h> diff --git a/tests/modules/os/cpuinfo.lua b/tests/modules/os/cpuinfo.lua new file mode 100644 index 000000000..dfb04350c --- /dev/null +++ b/tests/modules/os/cpuinfo.lua @@ -0,0 +1,7 @@ +function main() + print(os.cpuinfo()) + while true do + print("total: %d%%", math.floor(os.cpuinfo("usagerate") * 100)) + os.sleep(1000) + end +end diff --git a/tests/modules/os/meminfo.lua b/tests/modules/os/meminfo.lua new file mode 100644 index 000000000..e42d4350f --- /dev/null +++ b/tests/modules/os/meminfo.lua @@ -0,0 +1,6 @@ +function main() + while true do + print("%d%%", math.floor(os.meminfo("usagerate") * 100)) + os.sleep(1000) + end +end diff --git a/xmake/core/base/cpu.lua b/xmake/core/base/cpu.lua index a09aea4c9..aff0ee952 100644 --- a/xmake/core/base/cpu.lua +++ b/xmake/core/base/cpu.lua @@ -259,6 +259,22 @@ function cpu._info() return cpuinfo end +-- get cpu stats info +function cpu._statinfo(name) + local stats = cpu._STATS + local stime = cpu._STIME + if stats == nil or stime == nil or os.time() - stime > 1 then -- cache 1s + stats = os._cpuinfo() + cpu._STATS = stats + cpu._STIME = os.time() + end + if name then + return stats[name] + else + return stats + end +end + -- get vendor id function cpu.vendor() return cpu._info().vendor_id @@ -316,7 +332,12 @@ end -- get cpu number function cpu.number() - return os._cpuinfo().ncpu + return cpu._statinfo("ncpu") +end + +-- get cpu usage rate +function cpu.usagerate() + return cpu._statinfo("usagerate") end -- get cpu info @@ -328,8 +349,13 @@ function cpu.info(name) cpuinfo.march = cpu.march() cpuinfo.ncpu = cpu.number() cpuinfo.features = cpu.features() + cpuinfo.usagerate = cpu.usagerate() cpuinfo.model_name = cpu.model_name() - return name and cpuinfo[name] or cpuinfo + if name then + return cpuinfo[name] + else + return cpuinfo + end end -- return module diff --git a/xmake/core/base/memory.lua b/xmake/core/base/memory.lua index 3bd00813d..27b7331d6 100644 --- a/xmake/core/base/memory.lua +++ b/xmake/core/base/memory.lua @@ -32,11 +32,17 @@ function memory.info(name) meminfo = os._meminfo() if meminfo.totalsize and meminfo.availsize then meminfo.usagerate = (meminfo.totalsize - meminfo.availsize) / meminfo.totalsize + else + meminfo.usagerate = 0 end memory._MEMINFO = meminfo memory._MEMTIME = os.time() end - return name and meminfo[name] or meminfo + if name then + return meminfo[name] + else + return meminfo + end end -- return module |
