ruby-changes:35857
From: akr <ko1@a...>
Date: Wed, 15 Oct 2014 18:41:37 +0900 (JST)
Subject: [ruby-changes:35857] akr:r47939 (trunk): * ext/etc/etc.c (etc_nprocessors_affinity): use sched_getaffinity
akr 2014-10-15 18:41:25 +0900 (Wed, 15 Oct 2014) New Revision: 47939 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=47939 Log: * ext/etc/etc.c (etc_nprocessors_affinity): use sched_getaffinity for getting precious number of available cpus. * ext/etc/etc.c (etc_nprocessors): use etc_nprocessors_affinity if possible. [Feature #10267] etc-nprocessors-kosaki2.patch Modified files: trunk/ChangeLog trunk/configure.in trunk/ext/etc/etc.c Index: configure.in =================================================================== --- configure.in (revision 47938) +++ configure.in (revision 47939) @@ -2052,6 +2052,7 @@ AC_CHECK_FUNCS(pread) https://github.com/ruby/ruby/blob/trunk/configure.in#L2052 AC_CHECK_FUNCS(qsort_r) AC_CHECK_FUNCS(readlink) AC_CHECK_FUNCS(round) +AC_CHECK_FUNCS(sched_getaffinity) AC_CHECK_FUNCS(seekdir) AC_CHECK_FUNCS(select_large_fdset) AC_CHECK_FUNCS(sendfile) Index: ChangeLog =================================================================== --- ChangeLog (revision 47938) +++ ChangeLog (revision 47939) @@ -1,3 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Wed Oct 15 18:26:19 2014 KOSAKI Motohiro <kosaki.motohiro@g...> + + * ext/etc/etc.c (etc_nprocessors_affinity): use sched_getaffinity + for getting precious number of available cpus. + + * ext/etc/etc.c (etc_nprocessors): use etc_nprocessors_affinity if + possible. + + [Feature #10267] etc-nprocessors-kosaki2.patch + Wed Oct 15 17:53:28 2014 Tanaka Akira <akr@f...> * test/ruby/envutil.rb (assert_pattern_list) Renamed from Index: ext/etc/etc.c =================================================================== --- ext/etc/etc.c (revision 47938) +++ ext/etc/etc.c (revision 47939) @@ -30,6 +30,10 @@ https://github.com/ruby/ruby/blob/trunk/ext/etc/etc.c#L30 #include <sys/utsname.h> #endif +#ifdef HAVE_SCHED_GETAFFINITY +#include <sched.h> +#endif + static VALUE sPasswd; #ifdef HAVE_GETGRENT static VALUE sGroup; @@ -904,6 +908,54 @@ io_pathconf(VALUE io, VALUE arg) https://github.com/ruby/ruby/blob/trunk/ext/etc/etc.c#L908 #endif #if (defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)) || defined(_WIN32) + +#ifdef HAVE_SCHED_GETAFFINITY +static int +etc_nprocessors_affin(void) +{ + cpu_set_t *cpuset; + size_t size; + int ret; + int ncpus; + + /* + * XXX: + * man page says CPU_ALLOC takes number of cpus. But it is not accurate + * explanation. sched_getaffinity() returns EINVAL if cpuset bitmap is + * smaller than kernel internal bitmap. + * That said, sched_getaffinity() can fail when a kernel have sparse bitmap + * even if cpuset bitmap is larger than number of cpus. + * The precious way is to use /sys/devices/system/cpu/online. But there are + * two problems, + * - Costly calculation + * It is minor issue, but possibly kill the benefit of parallel processing. + * - No guarantee to exist /sys/devices/system/cpu/online + * This is an issue especially when using containers. + * So, we use hardcode number for workaround. Current linux kernel + * (Linux 3.17) support 8192 cpus at maximum. Then 16384 is enough large. + */ + ncpus = 16384; + + cpuset = CPU_ALLOC(ncpus); + if (!cpuset) { + return -1; + } + size = CPU_ALLOC_SIZE(ncpus); + CPU_ZERO_S(size, cpuset); + + ret = sched_getaffinity(0, size, cpuset); + if (ret==-1) { + goto free; + } + + ret = CPU_COUNT_S(size, cpuset); + free: + CPU_FREE(cpuset); + + return ret; +} +#endif + /* * Returns the number of online processors. * @@ -912,12 +964,21 @@ io_pathconf(VALUE io, VALUE arg) https://github.com/ruby/ruby/blob/trunk/ext/etc/etc.c#L964 * * This method is implemented as: * - sysconf(_SC_NPROCESSORS_ONLN): GNU/Linux, NetBSD, FreeBSD, OpenBSD, DragonFly BSD, OpenIndiana, Mac OS X, AIX + * - sched_getaffinity(): Linux * * Example: * * require 'etc' * p Etc.nprocessors #=> 4 * + * The result might be smaller number than physical cpus especially when ruby + * process is bound to specific cpus. This is intended for getting better + * parallel processing. + * + * Example: (Linux) + * + * $ taskset 0x3 ./ruby -retc -e "p Etc.nprocessors" #=> 2 + * */ static VALUE etc_nprocessors(VALUE obj) @@ -925,6 +986,17 @@ etc_nprocessors(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ext/etc/etc.c#L986 long ret; #if !defined(_WIN32) + +#ifdef HAVE_SCHED_GETAFFINITY + int ncpus; + + ncpus = etc_nprocessors_affin(); + if (ncpus != -1) { + return INT2NUM(ncpus); + } + /* fallback to _SC_NPROCESSORS_ONLN */ +#endif + errno = 0; ret = sysconf(_SC_NPROCESSORS_ONLN); if (ret == -1) { -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/