misc: implement uv_getrusage_thread (#4666)
Refs: https://github.com/libuv/libuv/issues/3119 Signed-off-by: Juan José Arboleda <soyjuanarbol@gmail.com> Co-authored-by: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
e59e2a9e49
commit
be8eec8c5a
@ -360,6 +360,17 @@ API
|
||||
On Windows not all fields are set, the unsupported fields are filled with zeroes.
|
||||
See :c:type:`uv_rusage_t` for more details.
|
||||
|
||||
.. c:function:: int uv_getrusage_thread(uv_rusage_t* rusage)
|
||||
|
||||
Gets the resource usage measures for the calling thread.
|
||||
|
||||
.. versionadded:: 1.50.0
|
||||
|
||||
.. note::
|
||||
Not supported on all platforms. May return `UV_ENOTSUP`.
|
||||
On macOS and Windows not all fields are set, the unsupported fields are filled with zeroes.
|
||||
See :c:type:`uv_rusage_t` for more details.
|
||||
|
||||
.. c:function:: uv_pid_t uv_os_getpid(void)
|
||||
|
||||
Returns the current process ID.
|
||||
|
||||
@ -1295,6 +1295,7 @@ typedef struct {
|
||||
} uv_rusage_t;
|
||||
|
||||
UV_EXTERN int uv_getrusage(uv_rusage_t* rusage);
|
||||
UV_EXTERN int uv_getrusage_thread(uv_rusage_t* rusage);
|
||||
|
||||
UV_EXTERN int uv_os_homedir(char* buffer, size_t* size);
|
||||
UV_EXTERN int uv_os_tmpdir(char* buffer, size_t* size);
|
||||
|
||||
@ -52,6 +52,8 @@
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
# include <mach/mach.h>
|
||||
# include <mach/thread_info.h>
|
||||
# include <sys/filio.h>
|
||||
# include <sys/sysctl.h>
|
||||
#endif /* defined(__APPLE__) */
|
||||
@ -999,10 +1001,10 @@ int uv__fd_exists(uv_loop_t* loop, int fd) {
|
||||
}
|
||||
|
||||
|
||||
int uv_getrusage(uv_rusage_t* rusage) {
|
||||
static int uv__getrusage(int who, uv_rusage_t* rusage) {
|
||||
struct rusage usage;
|
||||
|
||||
if (getrusage(RUSAGE_SELF, &usage))
|
||||
if (getrusage(who, &usage))
|
||||
return UV__ERR(errno);
|
||||
|
||||
rusage->ru_utime.tv_sec = usage.ru_utime.tv_sec;
|
||||
@ -1041,6 +1043,48 @@ int uv_getrusage(uv_rusage_t* rusage) {
|
||||
}
|
||||
|
||||
|
||||
int uv_getrusage(uv_rusage_t* rusage) {
|
||||
return uv__getrusage(RUSAGE_SELF, rusage);
|
||||
}
|
||||
|
||||
|
||||
int uv_getrusage_thread(uv_rusage_t* rusage) {
|
||||
#if defined(__APPLE__)
|
||||
mach_msg_type_number_t count;
|
||||
thread_basic_info_data_t info;
|
||||
kern_return_t kr;
|
||||
thread_t thread;
|
||||
|
||||
thread = mach_thread_self();
|
||||
count = THREAD_BASIC_INFO_COUNT;
|
||||
kr = thread_info(thread,
|
||||
THREAD_BASIC_INFO,
|
||||
(thread_info_t)&info,
|
||||
&count);
|
||||
|
||||
if (kr != KERN_SUCCESS) {
|
||||
mach_port_deallocate(mach_task_self(), thread);
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
memset(rusage, 0, sizeof(*rusage));
|
||||
|
||||
rusage->ru_utime.tv_sec = info.user_time.seconds;
|
||||
rusage->ru_utime.tv_usec = info.user_time.microseconds;
|
||||
rusage->ru_stime.tv_sec = info.system_time.seconds;
|
||||
rusage->ru_stime.tv_usec = info.system_time.microseconds;
|
||||
|
||||
mach_port_deallocate(mach_task_self(), thread);
|
||||
|
||||
return 0;
|
||||
|
||||
#elif defined(RUSAGE_THREAD)
|
||||
return uv__getrusage(RUSAGE_THREAD, rusage);
|
||||
#endif /* defined(__APPLE__) */
|
||||
return UV_ENOTSUP;
|
||||
}
|
||||
|
||||
|
||||
int uv__open_cloexec(const char* path, int flags) {
|
||||
#if defined(O_CLOEXEC)
|
||||
int fd;
|
||||
|
||||
@ -874,56 +874,100 @@ void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||
|
||||
|
||||
int uv_getrusage(uv_rusage_t *uv_rusage) {
|
||||
FILETIME createTime, exitTime, kernelTime, userTime;
|
||||
SYSTEMTIME kernelSystemTime, userSystemTime;
|
||||
PROCESS_MEMORY_COUNTERS memCounters;
|
||||
IO_COUNTERS ioCounters;
|
||||
FILETIME create_time, exit_time, kernel_time, user_time;
|
||||
SYSTEMTIME kernel_system_time, user_system_time;
|
||||
PROCESS_MEMORY_COUNTERS mem_counters;
|
||||
IO_COUNTERS io_counters;
|
||||
int ret;
|
||||
|
||||
ret = GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime);
|
||||
ret = GetProcessTimes(GetCurrentProcess(),
|
||||
&create_time,
|
||||
&exit_time,
|
||||
&kernel_time,
|
||||
&user_time);
|
||||
if (ret == 0) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
ret = FileTimeToSystemTime(&kernelTime, &kernelSystemTime);
|
||||
ret = FileTimeToSystemTime(&kernel_time, &kernel_system_time);
|
||||
if (ret == 0) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
ret = FileTimeToSystemTime(&userTime, &userSystemTime);
|
||||
ret = FileTimeToSystemTime(&user_time, &user_system_time);
|
||||
if (ret == 0) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
ret = GetProcessMemoryInfo(GetCurrentProcess(),
|
||||
&memCounters,
|
||||
sizeof(memCounters));
|
||||
&mem_counters,
|
||||
sizeof(mem_counters));
|
||||
if (ret == 0) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
ret = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
|
||||
ret = GetProcessIoCounters(GetCurrentProcess(), &io_counters);
|
||||
if (ret == 0) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
memset(uv_rusage, 0, sizeof(*uv_rusage));
|
||||
|
||||
uv_rusage->ru_utime.tv_sec = userSystemTime.wHour * 3600 +
|
||||
userSystemTime.wMinute * 60 +
|
||||
userSystemTime.wSecond;
|
||||
uv_rusage->ru_utime.tv_usec = userSystemTime.wMilliseconds * 1000;
|
||||
uv_rusage->ru_utime.tv_sec = user_system_time.wHour * 3600 +
|
||||
user_system_time.wMinute * 60 +
|
||||
user_system_time.wSecond;
|
||||
uv_rusage->ru_utime.tv_usec = user_system_time.wMilliseconds * 1000;
|
||||
|
||||
uv_rusage->ru_stime.tv_sec = kernelSystemTime.wHour * 3600 +
|
||||
kernelSystemTime.wMinute * 60 +
|
||||
kernelSystemTime.wSecond;
|
||||
uv_rusage->ru_stime.tv_usec = kernelSystemTime.wMilliseconds * 1000;
|
||||
uv_rusage->ru_stime.tv_sec = kernel_system_time.wHour * 3600 +
|
||||
kernel_system_time.wMinute * 60 +
|
||||
kernel_system_time.wSecond;
|
||||
uv_rusage->ru_stime.tv_usec = kernel_system_time.wMilliseconds * 1000;
|
||||
|
||||
uv_rusage->ru_majflt = (uint64_t) memCounters.PageFaultCount;
|
||||
uv_rusage->ru_maxrss = (uint64_t) memCounters.PeakWorkingSetSize / 1024;
|
||||
uv_rusage->ru_majflt = (uint64_t) mem_counters.PageFaultCount;
|
||||
uv_rusage->ru_maxrss = (uint64_t) mem_counters.PeakWorkingSetSize / 1024;
|
||||
|
||||
uv_rusage->ru_oublock = (uint64_t) ioCounters.WriteOperationCount;
|
||||
uv_rusage->ru_inblock = (uint64_t) ioCounters.ReadOperationCount;
|
||||
uv_rusage->ru_oublock = (uint64_t) io_counters.WriteOperationCount;
|
||||
uv_rusage->ru_inblock = (uint64_t) io_counters.ReadOperationCount;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_getrusage_thread(uv_rusage_t* uv_rusage) {
|
||||
FILETIME create_time, exit_time, kernel_time, user_time;
|
||||
SYSTEMTIME kernel_system_time, user_system_time;
|
||||
int ret;
|
||||
|
||||
ret = GetThreadTimes(GetCurrentThread(),
|
||||
&create_time,
|
||||
&exit_time,
|
||||
&kernel_time,
|
||||
&user_time);
|
||||
if (ret == 0) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
ret = FileTimeToSystemTime(&kernel_time, &kernel_system_time);
|
||||
if (ret == 0) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
ret = FileTimeToSystemTime(&user_time, &user_system_time);
|
||||
if (ret == 0) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
memset(uv_rusage, 0, sizeof(*uv_rusage));
|
||||
|
||||
uv_rusage->ru_utime.tv_sec = user_system_time.wHour * 3600 +
|
||||
user_system_time.wMinute * 60 +
|
||||
user_system_time.wSecond;
|
||||
uv_rusage->ru_utime.tv_usec = user_system_time.wMilliseconds * 1000;
|
||||
|
||||
uv_rusage->ru_stime.tv_sec = kernel_system_time.wHour * 3600 +
|
||||
kernel_system_time.wMinute * 60 +
|
||||
kernel_system_time.wSecond;
|
||||
uv_rusage->ru_stime.tv_usec = kernel_system_time.wMilliseconds * 1000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -236,5 +236,21 @@ TEST_IMPL(platform_output) {
|
||||
printf(" version: %s\n", uname.version);
|
||||
printf(" machine: %s\n", uname.machine);
|
||||
|
||||
ASSERT_OK(uv_getrusage_thread(&rusage));
|
||||
ASSERT_UINT64_GE(rusage.ru_utime.tv_sec, 0);
|
||||
ASSERT_UINT64_GE(rusage.ru_utime.tv_usec, 0);
|
||||
ASSERT_UINT64_GE(rusage.ru_stime.tv_sec, 0);
|
||||
ASSERT_UINT64_GE(rusage.ru_stime.tv_usec, 0);
|
||||
printf("uv_getrusage_thread:\n");
|
||||
printf(" user: %llu sec %llu microsec\n",
|
||||
(unsigned long long) rusage.ru_utime.tv_sec,
|
||||
(unsigned long long) rusage.ru_utime.tv_usec);
|
||||
printf(" system: %llu sec %llu microsec\n",
|
||||
(unsigned long long) rusage.ru_stime.tv_sec,
|
||||
(unsigned long long) rusage.ru_stime.tv_usec);
|
||||
printf(" page faults: %llu\n", (unsigned long long) rusage.ru_majflt);
|
||||
printf(" maximum resident set size: %llu\n",
|
||||
(unsigned long long) rusage.ru_maxrss);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user