grosser/parallel — pull request #80 by yaoguai (2013-09-30 03:23:46+00:00)
Title: More robust platform support

Recently I've been updating my fork of Parallel in a number of ways related to better platform support. Changes made are summarized below.

`Parallel.map` now will not attempt to use `Process.fork` unless it is actually implemented in the Ruby VM. Instead, if forking is not implemented, it will fall back to `work_direct`, along with a warning message to `$stderr`. This allows code utilizing Parallel to run on Windows platforms without blowing up, and still doing something sensible (albeit slower).

JRuby support is now explicitly added. Threads work very well on this platform, since there is no global interpreter lock. Multiprocessing with `Process.fork` is not possible in JRuby, though. Since this is the case, using Parallel with JRuby should default to utilizing threads, and use `processor_count` if no thread count is specified.

Physical processor counting methods for Linux and Windows were not quite accurate. For Linux, the method being used of multiplying the number of cores per processor by the number of processors, will usually work, but not always. Specifically, it would fail on systems with heterogeneous processor configurations. The new method instead maps all cores to their respective processors, and then uses that mapping to count the cores. Despite the extra steps involved, it is still very fast. For Windows, the previous code would fail for multiprocessor systems because there is a record in `Win32_Processor` for every socketed processor. The new method uses the field `NumberOfCores` rather than `NumberOfProcessors`, and adds the number of cores from all processors.

Processor counting has been updated to use a mostly heuristic approach, which is more reliable and comprehensive than trying to figure out the OS name for every system and version. The heuristic approach looks for certain executables and uses them directly to detect the number of processors. This means that even obscure systems with different names, but similar features, will work as expected. For example, DragonFly BSD has the OS name `dragonfly`, but because it works similarly to other BSDs, Parallel doesn't need to know anything specific about DragonFly in order to detect the number of processors on that platform, because it just sees that the system features are "BSD-ish." Another advantage of this approach is that it does not rely on the underlying shell environment, but rather uses `IO.popen` to call the executables directly. This approach avoids relying on the underlying shell and shell environment, such as $PATH. Windows processor detection has also been updated to utilize all records in `Win32_Processor`, so it is compatible with multiprocessor systems.

Related to the last change, the test for overriding the OS name has been removed, since processor detection does not simply depend on the OS name.

Instances of `RbConfig::CONFIG["host_os"]` have been changed to `RbConfig::CONFIG["target_os"]`. `host_os` indicates the OS used for compiling Ruby, whereas `target_os` indicates the OS that Ruby was compiled for. In nearly all cases these will be the same or very similar, but `target_os` is closer to the correct concept -- the OS that Ruby was compiled for.