unix,win: add uv_available_parallelism() (#3499)
Replacement for the usage pattern where people use uv_cpu_info() as an imperfect heuristic for determining the amount of parallelism that is available to their programs. Fixes #3493.
This commit is contained in:
parent
c40f8cb9f8
commit
f250c6c73e
@ -334,11 +334,30 @@ API
|
||||
|
||||
.. versionadded:: 1.16.0
|
||||
|
||||
.. c:function:: unsigned int uv_available_parallelism(void)
|
||||
|
||||
Returns an estimate of the default amount of parallelism a program should
|
||||
use. Always returns a non-zero value.
|
||||
|
||||
On Linux, inspects the calling thread's CPU affinity mask to determine if
|
||||
it has been pinned to specific CPUs.
|
||||
|
||||
On Windows, the available parallelism may be underreported on systems with
|
||||
more than 64 logical CPUs.
|
||||
|
||||
On other platforms, reports the number of CPUs that the operating system
|
||||
considers to be online.
|
||||
|
||||
.. versionadded:: 1.44.0
|
||||
|
||||
.. c:function:: int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count)
|
||||
|
||||
Gets information about the CPUs on the system. The `cpu_infos` array will
|
||||
have `count` elements and needs to be freed with :c:func:`uv_free_cpu_info`.
|
||||
|
||||
Use :c:func:`uv_available_parallelism` if you need to know how many CPUs
|
||||
are available for threads or child processes.
|
||||
|
||||
.. c:function:: void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count)
|
||||
|
||||
Frees the `cpu_infos` array previously allocated with :c:func:`uv_cpu_info`.
|
||||
|
||||
@ -1242,6 +1242,7 @@ UV_EXTERN uv_pid_t uv_os_getppid(void);
|
||||
UV_EXTERN int uv_os_getpriority(uv_pid_t pid, int* priority);
|
||||
UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority);
|
||||
|
||||
UV_EXTERN unsigned int uv_available_parallelism(void);
|
||||
UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
|
||||
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
|
||||
|
||||
|
||||
@ -84,6 +84,7 @@ extern char** environ;
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <sched.h>
|
||||
# include <sys/syscall.h>
|
||||
# define uv__accept4 accept4
|
||||
#endif
|
||||
@ -1648,3 +1649,35 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen) {
|
||||
/* Out of tokens (path entries), and no match found */
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
|
||||
unsigned int uv_available_parallelism(void) {
|
||||
#ifdef __linux__
|
||||
cpu_set_t set;
|
||||
long rc;
|
||||
|
||||
memset(&set, 0, sizeof(set));
|
||||
|
||||
/* sysconf(_SC_NPROCESSORS_ONLN) in musl calls sched_getaffinity() but in
|
||||
* glibc it's... complicated... so for consistency try sched_getaffinity()
|
||||
* before falling back to sysconf(_SC_NPROCESSORS_ONLN).
|
||||
*/
|
||||
if (0 == sched_getaffinity(0, sizeof(set), &set))
|
||||
rc = CPU_COUNT(&set);
|
||||
else
|
||||
rc = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
|
||||
if (rc < 1)
|
||||
rc = 1;
|
||||
|
||||
return (unsigned) rc;
|
||||
#else /* __linux__ */
|
||||
long rc;
|
||||
|
||||
rc = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if (rc < 1)
|
||||
rc = 1;
|
||||
|
||||
return (unsigned) rc;
|
||||
#endif /* __linux__ */
|
||||
}
|
||||
|
||||
@ -536,6 +536,23 @@ int uv_uptime(double* uptime) {
|
||||
}
|
||||
|
||||
|
||||
unsigned int uv_available_parallelism(void) {
|
||||
SYSTEM_INFO info;
|
||||
unsigned rc;
|
||||
|
||||
/* TODO(bnoordhuis) Use GetLogicalProcessorInformationEx() to support systems
|
||||
* with > 64 CPUs? See https://github.com/libuv/libuv/pull/3458
|
||||
*/
|
||||
GetSystemInfo(&info);
|
||||
|
||||
rc = info.dwNumberOfProcessors;
|
||||
if (rc < 1)
|
||||
rc = 1;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) {
|
||||
uv_cpu_info_t* cpu_infos;
|
||||
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
|
||||
|
||||
@ -41,6 +41,7 @@ TEST_IMPL(platform_output) {
|
||||
uv_interface_address_t* interfaces;
|
||||
uv_passwd_t pwd;
|
||||
uv_utsname_t uname;
|
||||
unsigned par;
|
||||
int count;
|
||||
int i;
|
||||
int err;
|
||||
@ -88,6 +89,10 @@ TEST_IMPL(platform_output) {
|
||||
printf(" maximum resident set size: %llu\n",
|
||||
(unsigned long long) rusage.ru_maxrss);
|
||||
|
||||
par = uv_available_parallelism();
|
||||
ASSERT_GE(par, 1);
|
||||
printf("uv_available_parallelism: %u\n", par);
|
||||
|
||||
err = uv_cpu_info(&cpus, &count);
|
||||
#if defined(__CYGWIN__) || defined(__MSYS__)
|
||||
ASSERT(err == UV_ENOSYS);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user