Skip to content

Commit 2d9d9b4

Browse files
committed
AtExit and ProcessorCounter are now in Utility module.
1 parent 0cd5c1f commit 2d9d9b4

File tree

7 files changed

+160
-159
lines changed

7 files changed

+160
-159
lines changed

lib/concurrent.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
require 'concurrent/version'
22

33
require 'concurrent/synchronization'
4-
require 'concurrent/at_exit'
54

65
require 'concurrent/configuration'
76

lib/concurrent/configuration.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
require 'thread'
22
require 'concurrent/atomics'
33
require 'concurrent/errors'
4-
require 'concurrent/at_exit'
54
require 'concurrent/executors'
6-
require 'concurrent/utility/processor_count'
5+
require 'concurrent/utility/at_exit'
6+
require 'concurrent/utility/processor_counter'
77
require 'concurrent/utility/deprecation'
88

99
module Concurrent

lib/concurrent/executor/executor_service.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
require 'concurrent/errors'
22
require 'concurrent/logging'
3-
require 'concurrent/at_exit'
43
require 'concurrent/atomic/event'
54
require 'concurrent/synchronization'
5+
require 'concurrent/utility/at_exit'
66
require 'concurrent/utility/deprecation'
77

88
module Concurrent

lib/concurrent/utilities.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1+
# DEPRECATED Remove this file at v1.0
12
require 'concurrent/utility/monotonic_time'
2-
require 'concurrent/utility/processor_count'
3+
require 'concurrent/utility/processor_counter'
34
require 'concurrent/utility/timeout'
45
require 'concurrent/utility/timer'
File renamed without changes.

lib/concurrent/utility/processor_count.rb

Lines changed: 0 additions & 154 deletions
This file was deleted.
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
require 'rbconfig'
2+
require 'concurrent/delay'
3+
4+
module Concurrent
5+
module Utility
6+
7+
class ProcessorCounter
8+
def initialize
9+
@processor_count = Delay.new { compute_processor_count }
10+
@physical_processor_count = Delay.new { compute_physical_processor_count }
11+
end
12+
13+
# Number of processors seen by the OS and used for process scheduling. For
14+
# performance reasons the calculated value will be memoized on the first
15+
# call.
16+
#
17+
# When running under JRuby the Java runtime call
18+
# `java.lang.Runtime.getRuntime.availableProcessors` will be used. According
19+
# to the Java documentation this "value may change during a particular
20+
# invocation of the virtual machine... [applications] should therefore
21+
# occasionally poll this property." Subsequently the result will NOT be
22+
# memoized under JRuby.
23+
#
24+
# On Windows the Win32 API will be queried for the
25+
# `NumberOfLogicalProcessors from Win32_Processor`. This will return the
26+
# total number "logical processors for the current instance of the
27+
# processor", which taked into account hyperthreading.
28+
#
29+
# * AIX: /usr/sbin/pmcycles (AIX 5+), /usr/sbin/lsdev
30+
# * BSD: /sbin/sysctl
31+
# * Cygwin: /proc/cpuinfo
32+
# * Darwin: /usr/bin/hwprefs, /usr/sbin/sysctl
33+
# * HP-UX: /usr/sbin/ioscan
34+
# * IRIX: /usr/sbin/sysconf
35+
# * Linux: /proc/cpuinfo
36+
# * Minix 3+: /proc/cpuinfo
37+
# * Solaris: /usr/sbin/psrinfo
38+
# * Tru64 UNIX: /usr/sbin/psrinfo
39+
# * UnixWare: /usr/sbin/psrinfo
40+
#
41+
# @return [Integer] number of processors seen by the OS or Java runtime
42+
#
43+
# @see https://github.com/grosser/parallel/blob/4fc8b89d08c7091fe0419ca8fba1ec3ce5a8d185/lib/parallel.rb
44+
#
45+
# @see http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html#availableProcessors()
46+
# @see http://msdn.microsoft.com/en-us/library/aa394373(v=vs.85).aspx
47+
def processor_count
48+
@processor_count.value
49+
end
50+
51+
# Number of physical processor cores on the current system. For performance
52+
# reasons the calculated value will be memoized on the first call.
53+
#
54+
# On Windows the Win32 API will be queried for the `NumberOfCores from
55+
# Win32_Processor`. This will return the total number "of cores for the
56+
# current instance of the processor." On Unix-like operating systems either
57+
# the `hwprefs` or `sysctl` utility will be called in a subshell and the
58+
# returned value will be used. In the rare case where none of these methods
59+
# work or an exception is raised the function will simply return 1.
60+
#
61+
# @return [Integer] number physical processor cores on the current system
62+
#
63+
# @see https://github.com/grosser/parallel/blob/4fc8b89d08c7091fe0419ca8fba1ec3ce5a8d185/lib/parallel.rb
64+
#
65+
# @see http://msdn.microsoft.com/en-us/library/aa394373(v=vs.85).aspx
66+
# @see http://www.unix.com/man-page/osx/1/HWPREFS/
67+
# @see http://linux.die.net/man/8/sysctl
68+
def physical_processor_count
69+
@physical_processor_count.value
70+
end
71+
72+
private
73+
74+
def compute_processor_count
75+
if Concurrent.on_jruby?
76+
java.lang.Runtime.getRuntime.availableProcessors
77+
else
78+
os_name = RbConfig::CONFIG["target_os"]
79+
if os_name =~ /mingw|mswin/
80+
require 'win32ole'
81+
result = WIN32OLE.connect("winmgmts://").ExecQuery(
82+
"select NumberOfLogicalProcessors from Win32_Processor")
83+
result.to_enum.collect(&:NumberOfLogicalProcessors).reduce(:+)
84+
elsif File.readable?("/proc/cpuinfo")
85+
IO.read("/proc/cpuinfo").scan(/^processor/).size
86+
elsif File.executable?("/usr/bin/hwprefs")
87+
IO.popen("/usr/bin/hwprefs thread_count").read.to_i
88+
elsif File.executable?("/usr/sbin/psrinfo")
89+
IO.popen("/usr/sbin/psrinfo").read.scan(/^.*on-*line/).size
90+
elsif File.executable?("/usr/sbin/ioscan")
91+
IO.popen("/usr/sbin/ioscan -kC processor") do |out|
92+
out.read.scan(/^.*processor/).size
93+
end
94+
elsif File.executable?("/usr/sbin/pmcycles")
95+
IO.popen("/usr/sbin/pmcycles -m").read.count("\n")
96+
elsif File.executable?("/usr/sbin/lsdev")
97+
IO.popen("/usr/sbin/lsdev -Cc processor -S 1").read.count("\n")
98+
elsif File.executable?("/usr/sbin/sysconf") and os_name =~ /irix/i
99+
IO.popen("/usr/sbin/sysconf NPROC_ONLN").read.to_i
100+
elsif File.executable?("/usr/sbin/sysctl")
101+
IO.popen("/usr/sbin/sysctl -n hw.ncpu").read.to_i
102+
elsif File.executable?("/sbin/sysctl")
103+
IO.popen("/sbin/sysctl -n hw.ncpu").read.to_i
104+
else
105+
1
106+
end
107+
end
108+
rescue
109+
return 1
110+
end
111+
112+
def compute_physical_processor_count
113+
ppc = case RbConfig::CONFIG["target_os"]
114+
when /darwin1/
115+
IO.popen("/usr/sbin/sysctl -n hw.physicalcpu").read.to_i
116+
when /linux/
117+
cores = {} # unique physical ID / core ID combinations
118+
phy = 0
119+
IO.read("/proc/cpuinfo").scan(/^physical id.*|^core id.*/) do |ln|
120+
if ln.start_with?("physical")
121+
phy = ln[/\d+/]
122+
elsif ln.start_with?("core")
123+
cid = phy + ":" + ln[/\d+/]
124+
cores[cid] = true if not cores[cid]
125+
end
126+
end
127+
cores.count
128+
when /mswin|mingw/
129+
require 'win32ole'
130+
result_set = WIN32OLE.connect("winmgmts://").ExecQuery(
131+
"select NumberOfCores from Win32_Processor")
132+
result_set.to_enum.collect(&:NumberOfCores).reduce(:+)
133+
else
134+
processor_count
135+
end
136+
# fall back to logical count if physical info is invalid
137+
ppc > 0 ? ppc : processor_count
138+
rescue
139+
return 1
140+
end
141+
end
142+
end
143+
144+
# create the default ProcessorCounter on load
145+
@processor_counter = Utility::ProcessorCounter.new
146+
singleton_class.send :attr_reader, :processor_counter
147+
148+
def self.processor_count
149+
processor_counter.processor_count
150+
end
151+
152+
def self.physical_processor_count
153+
processor_counter.physical_processor_count
154+
end
155+
end

0 commit comments

Comments
 (0)