concurrent-ruby 1.2.3 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c6483d36c3c75859c9b38b6ba2ba13577a0bb89b3b725a032d43f3543797099
4
- data.tar.gz: e94ac3e1ba23db29a7bf025736e34a4027ba7a137ae08b493c78ce3756803792
3
+ metadata.gz: de73718a68b7dd7b019703f83330c6f1ec241ed7b8aed1869c2b75983acb0df7
4
+ data.tar.gz: ef715c39caf7f29e13a926794ffc09a044d956c6c2b7461bcd6aaf23ed848436
5
5
  SHA512:
6
- metadata.gz: dc0353e60638a409bf891d663626bd2c1c5f05206c08036326d63e239bfe0ea7e1e3480982c75fe44f9d416a7f76a66a2a2aeef78fc60084ed7ff94c7d3181d9
7
- data.tar.gz: 24bdd3a040528c05061ec15b4057184be96fa933f69f3321755e8583ba8e6175beec48c36f1671cc3dad7e413588c9601c7f0e5b503b3de947dff63c2ba76b1e
6
+ metadata.gz: c9d669f4db5272834efb50a4cd21517e322a50f3750d1412f65aae78b67f54ab3844ce129dbab042670757ecac9765aa1991762fcbe0bf9c6aa5b954d01a7f83
7
+ data.tar.gz: e659fb2f13b77ae537c82d76508e929716c0d40cad91ab5ea0df47672a13aaebcd016df9eb3ccde1278bdb75fe9a7bb0386407bf7ba22574c9f4d9ed5cbd6b4f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  ## Current
2
2
 
3
+ ## Release v1.3.2, edge v0.7.1 (29 May 2024)
4
+
5
+ concurrent-ruby:
6
+
7
+ * (#1051) Remove dependency on `win32ole`.
8
+
9
+ concurrent-ruby-edge:
10
+
11
+ * (#1052) Fix dependency on `concurrent-ruby` to allow the latest release.
12
+
13
+ ## Release v1.3.1 (29 May 2024)
14
+
15
+ * Release 1.3.0 was broken when pushed to RubyGems. 1.3.1 is a packaging fix.
16
+
17
+ ## Release v1.3.0 (28 May 2024)
18
+
19
+ * (#1042) Align Java Executor Service behavior for `shuttingdown?`, `shutdown?`
20
+ * (#1038) Add `Concurrent.available_processor_count` that is cgroups aware.
21
+
3
22
  ## Release v1.2.3 (16 Jan 2024)
4
23
 
5
24
  * See [the GitHub release](https://github.com/ruby-concurrency/concurrent-ruby/releases/tag/v1.2.3) for details.
data/Rakefile CHANGED
@@ -28,6 +28,10 @@ unless Concurrent.on_jruby? || Concurrent.on_truffleruby?
28
28
  end
29
29
  end
30
30
 
31
+ def which?(executable)
32
+ !`which #{executable} 2>/dev/null`.empty?
33
+ end
34
+
31
35
  require 'rake_compiler_dock'
32
36
  namespace :repackage do
33
37
  desc '* with Windows fat distributions'
@@ -42,12 +46,19 @@ namespace :repackage do
42
46
  Rake::Task['lib/concurrent-ruby/concurrent/concurrent_ruby.jar'].invoke
43
47
 
44
48
  # build all gem files
49
+ rack_compiler_dock_kwargs = {}
50
+ if which?('podman') and (!which?('docker') || `docker --version`.include?('podman'))
51
+ # podman and only podman available, so RakeCompilerDock will use podman, otherwise it uses docker
52
+ rack_compiler_dock_kwargs = {
53
+ options: ['--privileged'], # otherwise the directory in the image is empty
54
+ runas: false
55
+ }
56
+ end
45
57
  %w[x86-mingw32 x64-mingw32].each do |plat|
46
58
  RakeCompilerDock.sh(
47
59
  "bundle install --local && bundle exec rake native:#{plat} gem --trace",
48
60
  platform: plat,
49
- options: ['--privileged'], # otherwise the directory in the image is empty
50
- runas: false)
61
+ **rack_compiler_dock_kwargs)
51
62
  end
52
63
  end
53
64
  end
@@ -256,10 +267,12 @@ namespace :release do
256
267
 
257
268
  Bundler.with_original_env do
258
269
  sh 'ruby -v'
270
+ sh 'bundle install'
259
271
  sh 'bundle exec rake spec:installed'
260
272
 
261
- env = { "PATH" => "#{ENV['CONCURRENT_JRUBY_HOME']}/bin:#{ENV['PATH']}" }
273
+ env = { "PATH" => "#{ENV.fetch('CONCURRENT_JRUBY_HOME')}/bin:#{ENV['PATH']}" }
262
274
  sh env, 'ruby -v'
275
+ sh env, 'bundle install'
263
276
  sh env, 'bundle exec rake spec:installed'
264
277
  end
265
278
 
@@ -271,8 +284,8 @@ namespace :release do
271
284
  task :publish => ['publish:ask', 'publish:tag', 'publish:rubygems', 'publish:post_steps']
272
285
 
273
286
  namespace :publish do
274
- publish_base = true
275
- publish_edge = false
287
+ publish_base = nil
288
+ publish_edge = nil
276
289
 
277
290
  task :ask do
278
291
  begin
@@ -280,8 +293,15 @@ namespace :release do
280
293
  input = STDIN.gets.strip.downcase
281
294
  end until %w(y n).include?(input)
282
295
  exit 1 if input == 'n'
296
+
297
+ begin
298
+ STDOUT.puts 'Do you want to publish `concurrent-ruby`? (y/n)'
299
+ input = STDIN.gets.strip.downcase
300
+ end until %w(y n).include?(input)
301
+ publish_base = input == 'y'
302
+
283
303
  begin
284
- STDOUT.puts 'It will publish `concurrent-ruby`. Do you want to publish `concurrent-ruby-edge`? (y/n)'
304
+ STDOUT.puts 'Do you want to publish `concurrent-ruby-edge`? (y/n)'
285
305
  input = STDIN.gets.strip.downcase
286
306
  end until %w(y n).include?(input)
287
307
  publish_edge = input == 'y'
@@ -57,15 +57,11 @@ if Concurrent.on_jruby?
57
57
  end
58
58
 
59
59
  def ns_shuttingdown?
60
- if @executor.respond_to? :isTerminating
61
- @executor.isTerminating
62
- else
63
- false
64
- end
60
+ @executor.isShutdown && !@executor.isTerminated
65
61
  end
66
62
 
67
63
  def ns_shutdown?
68
- @executor.isShutdown || @executor.isTerminated
64
+ @executor.isTerminated
69
65
  end
70
66
 
71
67
  class Job
@@ -11,6 +11,7 @@ module Concurrent
11
11
  def initialize
12
12
  @processor_count = Delay.new { compute_processor_count }
13
13
  @physical_processor_count = Delay.new { compute_physical_processor_count }
14
+ @cpu_quota = Delay.new { compute_cpu_quota }
14
15
  end
15
16
 
16
17
  def processor_count
@@ -21,6 +22,25 @@ module Concurrent
21
22
  @physical_processor_count.value
22
23
  end
23
24
 
25
+ def available_processor_count
26
+ cpu_count = processor_count.to_f
27
+ quota = cpu_quota
28
+
29
+ return cpu_count if quota.nil?
30
+
31
+ # cgroup cpus quotas have no limits, so they can be set to higher than the
32
+ # real count of cores.
33
+ if quota > cpu_count
34
+ cpu_count
35
+ else
36
+ quota
37
+ end
38
+ end
39
+
40
+ def cpu_quota
41
+ @cpu_quota.value
42
+ end
43
+
24
44
  private
25
45
 
26
46
  def compute_processor_count
@@ -48,10 +68,20 @@ module Concurrent
48
68
  end
49
69
  cores.count
50
70
  when /mswin|mingw/
51
- require 'win32ole'
52
- result_set = WIN32OLE.connect("winmgmts://").ExecQuery(
53
- "select NumberOfCores from Win32_Processor")
54
- result_set.to_enum.collect(&:NumberOfCores).reduce(:+)
71
+ # Get-CimInstance introduced in PowerShell 3 or earlier: https://learn.microsoft.com/en-us/previous-versions/powershell/module/cimcmdlets/get-ciminstance?view=powershell-3.0
72
+ result = run('powershell -command "Get-CimInstance -ClassName Win32_Processor | Select-Object -Property NumberOfCores"')
73
+ if !result || $?.exitstatus != 0
74
+ # fallback to deprecated wmic for older systems
75
+ result = run("wmic cpu get NumberOfCores")
76
+ end
77
+ if !result || $?.exitstatus != 0
78
+ # Bail out if both commands returned something unexpected
79
+ processor_count
80
+ else
81
+ # powershell: "\nNumberOfCores\n-------------\n 4\n\n\n"
82
+ # wmic: "NumberOfCores \n\n4 \n\n\n\n"
83
+ result.scan(/\d+/).map(&:to_i).reduce(:+)
84
+ end
55
85
  else
56
86
  processor_count
57
87
  end
@@ -60,6 +90,29 @@ module Concurrent
60
90
  rescue
61
91
  return 1
62
92
  end
93
+
94
+ def run(command)
95
+ IO.popen(command, &:read)
96
+ rescue Errno::ENOENT
97
+ end
98
+
99
+ def compute_cpu_quota
100
+ if RbConfig::CONFIG["target_os"].include?("linux")
101
+ if File.exist?("/sys/fs/cgroup/cpu.max")
102
+ # cgroups v2: https://docs.kernel.org/admin-guide/cgroup-v2.html#cpu-interface-files
103
+ cpu_max = File.read("/sys/fs/cgroup/cpu.max")
104
+ return nil if cpu_max.start_with?("max ") # no limit
105
+ max, period = cpu_max.split.map(&:to_f)
106
+ max / period
107
+ elsif File.exist?("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us")
108
+ # cgroups v1: https://kernel.googlesource.com/pub/scm/linux/kernel/git/glommer/memcg/+/cpu_stat/Documentation/cgroups/cpu.txt
109
+ max = File.read("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us").to_i
110
+ return nil if max == 0
111
+ period = File.read("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us").to_f
112
+ max / period
113
+ end
114
+ end
115
+ end
63
116
  end
64
117
  end
65
118
 
@@ -107,4 +160,31 @@ module Concurrent
107
160
  def self.physical_processor_count
108
161
  processor_counter.physical_processor_count
109
162
  end
163
+
164
+ # Number of processors cores available for process scheduling.
165
+ # Returns `nil` if there is no #cpu_quota, or a `Float` if the
166
+ # process is inside a cgroup with a dedicated CPU quota (typically Docker).
167
+ #
168
+ # For performance reasons the calculated value will be memoized on the first
169
+ # call.
170
+ #
171
+ # @return [nil, Float] number of available processors
172
+ def self.available_processor_count
173
+ processor_counter.available_processor_count
174
+ end
175
+
176
+ # The maximum number of processors cores available for process scheduling.
177
+ # Returns `nil` if there is no enforced limit, or a `Float` if the
178
+ # process is inside a cgroup with a dedicated CPU quota (typically Docker).
179
+ #
180
+ # Note that nothing prevents setting a CPU quota higher than the actual number of
181
+ # cores on the system.
182
+ #
183
+ # For performance reasons the calculated value will be memoized on the first
184
+ # call.
185
+ #
186
+ # @return [nil, Float] Maximum number of available processors as set by a cgroup CPU quota, or nil if none set
187
+ def self.cpu_quota
188
+ processor_counter.cpu_quota
189
+ end
110
190
  end
@@ -1,3 +1,3 @@
1
1
  module Concurrent
2
- VERSION = '1.2.3'
2
+ VERSION = '1.3.2'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concurrent-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.3
4
+ version: 1.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jerry D'Antonio
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-01-16 00:00:00.000000000 Z
13
+ date: 2024-06-07 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description: |
16
16
  Modern concurrency tools including agents, futures, promises, thread pools, actors, supervisors, and more.