• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ruby-concurrency / concurrent-ruby / #2796

16 Feb 2015 06:15PM UTC coverage: 92.313% (+0.7%) from 91.65%
#2796

push

lucasallan
Merge pull request #247 from ruby-concurrency/atomic-java-improvements

Uses getRuntime() to create boolean and fixnum objects in JRuby.

2882 of 3122 relevant lines covered (92.31%)

459.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

56.72
/lib/concurrent/utility/processor_count.rb
1
require 'rbconfig'
1✔
2
require 'concurrent/delay'
1✔
3
require 'concurrent/executor/immediate_executor'
1✔
4

5
module Concurrent
1✔
6

7
  class ProcessorCounter
1✔
8
    def initialize
1✔
9
      immediate_executor        = ImmediateExecutor.new
1✔
10
      @processor_count          = Delay.new(executor: immediate_executor) { compute_processor_count }
2✔
11
      @physical_processor_count = Delay.new(executor: immediate_executor) { compute_physical_processor_count }
2✔
12
    end
13

14
    # Number of processors seen by the OS and used for process scheduling. For
15
    # performance reasons the calculated value will be memoized on the first
16
    # call.
17
    #
18
    # When running under JRuby the Java runtime call
19
    # `java.lang.Runtime.getRuntime.availableProcessors` will be used. According
20
    # to the Java documentation this "value may change during a particular
21
    # invocation of the virtual machine... [applications] should therefore
22
    # occasionally poll this property." Subsequently the result will NOT be
23
    # memoized under JRuby.
24
    #
25
    # On Windows the Win32 API will be queried for the
26
    # `NumberOfLogicalProcessors from Win32_Processor`. This will return the
27
    # total number "logical processors for the current instance of the
28
    # processor", which taked into account hyperthreading.
29
    #
30
    # * AIX: /usr/sbin/pmcycles (AIX 5+), /usr/sbin/lsdev
31
    # * BSD: /sbin/sysctl
32
    # * Cygwin: /proc/cpuinfo
33
    # * Darwin: /usr/bin/hwprefs, /usr/sbin/sysctl
34
    # * HP-UX: /usr/sbin/ioscan
35
    # * IRIX: /usr/sbin/sysconf
36
    # * Linux: /proc/cpuinfo
37
    # * Minix 3+: /proc/cpuinfo
38
    # * Solaris: /usr/sbin/psrinfo
39
    # * Tru64 UNIX: /usr/sbin/psrinfo
40
    # * UnixWare: /usr/sbin/psrinfo
41
    #
42
    # @return [Integer] number of processors seen by the OS or Java runtime
43
    #
44
    # @see https://github.com/grosser/parallel/blob/4fc8b89d08c7091fe0419ca8fba1ec3ce5a8d185/lib/parallel.rb
45
    #
46
    # @see http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html#availableProcessors()
47
    # @see http://msdn.microsoft.com/en-us/library/aa394373(v=vs.85).aspx
48
    def processor_count
1✔
49
      @processor_count.value
805✔
50
    end
51

52
    # Number of physical processor cores on the current system. For performance
53
    # reasons the calculated value will be memoized on the first call.
54
    #
55
    # On Windows the Win32 API will be queried for the `NumberOfCores from
56
    # Win32_Processor`. This will return the total number "of cores for the
57
    # current instance of the processor." On Unix-like operating systems either
58
    # the `hwprefs` or `sysctl` utility will be called in a subshell and the
59
    # returned value will be used. In the rare case where none of these methods
60
    # work or an exception is raised the function will simply return 1.
61
    #
62
    # @return [Integer] number physical processor cores on the current system
63
    #
64
    # @see https://github.com/grosser/parallel/blob/4fc8b89d08c7091fe0419ca8fba1ec3ce5a8d185/lib/parallel.rb
65
    #
66
    # @see http://msdn.microsoft.com/en-us/library/aa394373(v=vs.85).aspx
67
    # @see http://www.unix.com/man-page/osx/1/HWPREFS/
68
    # @see http://linux.die.net/man/8/sysctl
69
    def physical_processor_count
1✔
70
      @physical_processor_count.value
2✔
71
    end
72

73
    private
1✔
74

75
    def compute_processor_count
1✔
76
      if RUBY_PLATFORM == 'java'
1✔
77
        java.lang.Runtime.getRuntime.availableProcessors
×
78
      else
79
        os_name = RbConfig::CONFIG["target_os"]
1✔
80
        if os_name =~ /mingw|mswin/
1✔
81
          require 'win32ole'
×
82
          result = WIN32OLE.connect("winmgmts://").ExecQuery(
×
83
              "select NumberOfLogicalProcessors from Win32_Processor")
84
          result.to_enum.collect(&:NumberOfLogicalProcessors).reduce(:+)
×
85
        elsif File.readable?("/proc/cpuinfo")
1✔
86
          IO.read("/proc/cpuinfo").scan(/^processor/).size
1✔
87
        elsif File.executable?("/usr/bin/hwprefs")
×
88
          IO.popen("/usr/bin/hwprefs thread_count").read.to_i
×
89
        elsif File.executable?("/usr/sbin/psrinfo")
×
90
          IO.popen("/usr/sbin/psrinfo").read.scan(/^.*on-*line/).size
×
91
        elsif File.executable?("/usr/sbin/ioscan")
×
92
          IO.popen("/usr/sbin/ioscan -kC processor") do |out|
×
93
            out.read.scan(/^.*processor/).size
×
94
          end
95
        elsif File.executable?("/usr/sbin/pmcycles")
×
96
          IO.popen("/usr/sbin/pmcycles -m").read.count("\n")
×
97
        elsif File.executable?("/usr/sbin/lsdev")
×
98
          IO.popen("/usr/sbin/lsdev -Cc processor -S 1").read.count("\n")
×
99
        elsif File.executable?("/usr/sbin/sysconf") and os_name =~ /irix/i
×
100
          IO.popen("/usr/sbin/sysconf NPROC_ONLN").read.to_i
×
101
        elsif File.executable?("/usr/sbin/sysctl")
×
102
          IO.popen("/usr/sbin/sysctl -n hw.ncpu").read.to_i
×
103
        elsif File.executable?("/sbin/sysctl")
×
104
          IO.popen("/sbin/sysctl -n hw.ncpu").read.to_i
×
105
        else
106
          1
×
107
        end
108
      end
109
    rescue
110
      return 1
×
111
    end
112

113
    def compute_physical_processor_count
1✔
114
      ppc = case RbConfig::CONFIG["target_os"]
1✔
115
            when /darwin1/
116
              IO.popen("/usr/sbin/sysctl -n hw.physicalcpu").read.to_i
×
117
            when /linux/
118
              cores = {} # unique physical ID / core ID combinations
1✔
119
              phy   = 0
1✔
120
              IO.read("/proc/cpuinfo").scan(/^physical id.*|^core id.*/) do |ln|
1✔
121
                if ln.start_with?("physical")
128✔
122
                  phy = ln[/\d+/]
64✔
123
                elsif ln.start_with?("core")
64✔
124
                  cid        = phy + ":" + ln[/\d+/]
64✔
125
                  cores[cid] = true if not cores[cid]
64✔
126
                end
127
              end
128
              cores.count
1✔
129
            when /mswin|mingw/
130
              require 'win32ole'
×
131
              result_set = WIN32OLE.connect("winmgmts://").ExecQuery(
×
132
                  "select NumberOfCores from Win32_Processor")
133
              result_set.to_enum.collect(&:NumberOfCores).reduce(:+)
×
134
            else
135
              processor_count
×
136
            end
137
      # fall back to logical count if physical info is invalid
138
      ppc > 0 ? ppc : processor_count
1✔
139
    rescue
140
      return 1
×
141
    end
142
  end
143

144
  # create the default ProcessorCounter on load
145
  @processor_counter = ProcessorCounter.new
1✔
146
  singleton_class.send :attr_reader, :processor_counter
1✔
147

148
  def self.processor_count
1✔
149
    processor_counter.processor_count
805✔
150
  end
151

152
  def self.physical_processor_count
1✔
153
    processor_counter.physical_processor_count
2✔
154
  end
155

156
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc