I already found a solution for \"Most unixes\" via cat /proc/cpuinfo
, but a pure-Ruby solution would be nicer.
I am currently using this, which covers all os. https://github.com/grosser/parallel/blob/master/lib/parallel.rb#L63
def self.processor_count
case RbConfig::CONFIG['host_os']
when /darwin9/
`hwprefs cpu_count`.to_i
when /darwin/
((`which hwprefs` != '') ? `hwprefs thread_count` : `sysctl -n hw.ncpu`).to_i
when /linux/
`cat /proc/cpuinfo | grep processor | wc -l`.to_i
when /freebsd/
`sysctl -n hw.ncpu`.to_i
when /mswin|mingw/
require 'win32ole'
wmi = WIN32OLE.connect("winmgmts://")
cpu = wmi.ExecQuery("select NumberOfCores from Win32_Processor") # TODO count hyper-threaded in this
cpu.to_enum.first.NumberOfCores
end
end
EDIT: Now rails ships with concurrent-ruby as a dependency so it's probably the best solution;
$ gem install concurrent-ruby
$ irb
irb(main):001:0> require 'concurrent'
=> true
irb(main):002:0> Concurrent.processor_count
=> 8
irb(main):003:0> Concurrent.physical_processor_count
=> 4
see http://ruby-concurrency.github.io/concurrent-ruby/root/Concurrent.html for more info. Because it does both physical and logical cores, it's better than the inbuilt Etc.nprocessors
.
and here is the previous answer;
$ gem install facter
$ irb
irb(main):001:0> require 'facter'
=> true
irb(main):002:0> puts Facter.value('processors')['count']
4
=> nil
irb(main):003:0>
This facter gem is the best if you want other facts about the system too, it's not platform specific and designed to do this exact thing.
UPDATE: updated to include Nathan Kleyn's tip on the api change.
I tried using Facter
but found it a bit slow. I tried system
gem and found it a lot faster. It is also very easy to use: System::CPU.count
.
I found something recently that may have to be taken into consideration. You can deactivate processors (take them offline), and then facter processorcount (plus some of the other methods above) gives the wrong result. You can count processor lines in /proc/cpuinfo, as long as you do it correctly. If you just populate an array with index numbers of the procs, if you have gaps in the procs (as in, procs 0,1,2,10,11,12 are active, all others to 20 say are inactive), it will automatically spring indexes 3-9 into existence (sort of), at least Array#size will report 13 in that case. You would have to do #compact to get the number of active processors. However, if you want total processors, perhaps better is looking at /sys/devices/system/cpu[0-9], and count that up. That will give you the total number of processors, but not how many (or which ones) are active.
Just something to think about. I trying to put through a patch to facter to add an activeprocessorcount and totalprocessorcount fact.
Combination of @grosser's and @paxdiablo's answer, since on my system (winxp) win32_computersystem doesn't have any processor info; this works though:
require 'win32ole'
wmi = WIN32OLE.connect("winmgmts://")
info = wmi.ExecQuery ("select NumberOfCores from Win32_processor")
puts info.to_enum.first.NumberOfCores
To see what's available on your system, run this from powershell (i used 1.0 in this case):
Get-WmiObject -list
(might want to pipe to grep if you've got cygwin installed)
Surely if you can cat
it, you can open, read and close it using the standard features of the language without resorting to a system()
-type call.
You may just need to detect what platform you're on dynamically and either:
/proc/cpuinfo
"file" for Linux; orThat last line can use:
require 'win32ole'
wmi = WIN32OLE.connect("winmgmts://")
info = wmi.ExecQuery ("select * from Win32_ComputerSystem")
Then use info's NumberOfProcessors item.