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

ruby-concurrency / concurrent-ruby / #2765

15 Jun 2014 12:51PM UTC coverage: 92.505% (-3.9%) from 96.422%
#2765

push

jdantonio
Fixed doc entry mistakenly removed from .gitignore.

2629 of 2842 relevant lines covered (92.51%)

695.93 hits per line

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

55.38
/lib/concurrent/utility/processor_count.rb
1
require 'rbconfig'
1✔
2
require 'concurrent/delay'
1✔
3

4
module Concurrent
1✔
5

6
  class ProcessorCounter
1✔
7
    def initialize
1✔
8
      @processor_count          = Delay.new { compute_processor_count }
2✔
9
      @physical_processor_count = Delay.new { compute_physical_processor_count }
2✔
10
    end
11

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

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

67
    private
1✔
68

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

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

138
  # create the default ProcessorCounter on load
139
  @processor_counter = ProcessorCounter.new
1✔
140
  singleton_class.send :attr_reader, :processor_counter
1✔
141

142
  def self.processor_count
1✔
143
    processor_counter.processor_count
405✔
144
  end
145

146
  def self.physical_processor_count
1✔
147
    processor_counter.physical_processor_count
2✔
148
  end
149

150
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