Permalink
Browse files

Add CPU count autodetect.

  • Loading branch information...
1 parent 56b44c9 commit 95514fa764529d4d485d07e9686cd42a8e45e785 @jimweirich committed Jun 20, 2013
Showing with 126 additions and 3 deletions.
  1. +1 −0 lib/rake.rb
  2. +9 −1 lib/rake/application.rb
  3. +100 −0 lib/rake/cpu_counter.rb
  4. +5 −0 lib/rake/rake_module.rb
  5. +11 −2 test/test_rake_application_options.rb
View
1 lib/rake.rb
@@ -41,6 +41,7 @@
require 'rake/win32'
require 'rake/linked_list'
+require 'rake/cpu_counter'
require 'rake/scope'
require 'rake/task_argument_error'
require 'rake/rule_recursion_overflow_error'
View
10 lib/rake/application.rb
@@ -409,7 +409,15 @@ def standard_rake_options
"Specifies the maximum number of tasks to execute in parallel. " +
"(default is 2)",
lambda { |value|
- options.thread_pool_size = [(value || 3).to_i, 3].max - 1
+ if value == 'max'
+ value = FIXNUM_MAX
+ elsif value =~ /^\d+$/
+ value = value.to_i
+ else
+ value = Rake.suggested_thread_count
+ end
+ value = 1 if value < 1
+ options.thread_pool_size = value - 1
}
],
['--job-stats [LEVEL]',
View
100 lib/rake/cpu_counter.rb
@@ -0,0 +1,100 @@
+require 'rbconfig'
+
+module Rake
+
+ # Based on a script at:
+ # http://stackoverflow.com/questions/891537/ruby-detect-number-of-cpus-installed
+ class CpuCounter
+ def self.count
+ new.count_with_default
+ end
+
+ def count_with_default(default=4)
+ count || default
+ rescue StandardError
+ default
+ end
+
+ def count
+ if defined?(Java::Java)
+ count_via_java_runtime
+ else
+ case RbConfig::CONFIG['host_os']
+ when /darwin9/
+ count_via_hwprefs_cpu_count
+ when /darwin/
+ count_via_hwprefs_thread_count || count_via_sysctl
+ when /linux/
+ count_via_cpuinfo
+ when /freebsd/
+ count_via_sysctl
+ when /mswin|mingw/
+ count_via_win32
+ else
+ # Try everything
+ count_via_win32 ||
+ count_via_sysctl ||
+ count_via_hwprefs_thread_count ||
+ count_via_hwprefs_cpu_count
+ end
+ end
+ end
+
+ def count_via_java_runtime
+ Java::Java.lang.Runtime.getRuntime.availableProcessors
+ rescue StandardError
+ nil
+ end
+
+ def count_via_win32
+ 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
+ rescue StandardError
+ nil
+ end
+
+ def count_via_cpuinfo
+ open('/proc/cpuinfo') { |f| f.readlines }.grep(/processor/).size
+ rescue StandardError
+ nil
+ end
+
+ def count_via_hwprefs_thread_count
+ run 'hwprefs', 'thread_count'
+ end
+
+ def count_via_hwprefs_cpu_count
+ run 'hwprefs', 'cpu_count'
+ end
+
+ def count_via_sysctl
+ run 'sysctl', '-n hw.ncpu'
+ end
+
+ def run(command, args)
+ cmd = resolve_command(command)
+ if cmd
+ `#{cmd} #{args}`.to_i
+ else
+ nil
+ end
+ end
+
+ def resolve_command(command)
+ look_for_command("/usr/sbin", command) ||
+ look_for_command("/sbin", command) ||
+ in_path_command(command)
+ end
+
+ def look_for_command(dir, command)
+ path = File.join(dir, command)
+ File.exist?(path) ? path : nil
+ end
+
+ def in_path_command(command)
+ `which #{command}` != '' ? command : nil
+ end
+ end
+end
View
5 lib/rake/rake_module.rb
@@ -15,6 +15,11 @@ def application=(app)
@application = app
end
+ def suggested_thread_count
+ cpus = Rake::CpuCounter.count || 2
+ cpus + 4
+ end
+
# Return the original directory where the Rake application was started.
def original_dir
application.original_dir
View
13 test/test_rake_application_options.rb
@@ -111,14 +111,23 @@ def test_help
end
def test_jobs
+ flags(['--jobs', '0'], ['-j', '0']) do |opts|
+ assert_equal 0, opts.thread_pool_size
+ end
+ flags(['--jobs', '1'], ['-j', '1']) do |opts|
+ assert_equal 0, opts.thread_pool_size
+ end
flags(['--jobs', '4'], ['-j', '4']) do |opts|
assert_equal 3, opts.thread_pool_size
end
flags(['--jobs', 'asdas'], ['-j', 'asdas']) do |opts|
- assert_equal 2, opts.thread_pool_size
+ assert_equal Rake.suggested_thread_count-1, opts.thread_pool_size
+ end
+ flags(['--jobs', 'max'], ['-j', 'max']) do |opts|
+ assert opts.thread_pool_size > 1_000_000, "thread pool size should be huge (was #{opts.thread_pool_size})"
end
flags('--jobs', '-j') do |opts|
- assert_equal 2, opts.thread_pool_size
+ assert_equal Rake.suggested_thread_count-1, opts.thread_pool_size
end
end

0 comments on commit 95514fa

Please sign in to comment.