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

ruby-concurrency / concurrent-ruby / #2702

12 Feb 2015 06:34PM UTC coverage: 92.31% (+0.6%) from 91.69%
#2702

push

lucasallan
Merge pull request #238 from ruby-concurrency/semaphore-pure-java

Implementation of Concurrent::JavaSemaphore in pure Java.

2881 of 3121 relevant lines covered (92.31%)

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

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

69
    private
1✔
70

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

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

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

144
  def self.processor_count
1✔
145
    processor_counter.processor_count
800✔
146
  end
147

148
  def self.physical_processor_count
1✔
149
    processor_counter.physical_processor_count
2✔
150
  end
151

152
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