concurrent-ruby 1.3.1 → 1.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -1
- data/Gemfile +5 -5
- data/Rakefile +48 -25
- data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
- data/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +55 -10
- data/lib/concurrent-ruby/concurrent/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 01c9677c137013ec86d98778a4aa6a9e69bca9b0ae29e923a37254c9cdc515fe
|
4
|
+
data.tar.gz: 3be169b6d0a11914f85e4a0e1221cd5c122bd59035abe9718892e1a3b4bc690b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 89544dfc5575906cac0f5c57ce5348b944a70a6f77154fb70d0f185b9cc79344a5bb5147a7cf22808e071b4213c80c94e3036b98a2f4102018daf8ba16492db8
|
7
|
+
data.tar.gz: f084a5a9aa8c6e2ad305fe360f1e8e3b264ad0b45f7add6c04561ff4945cbf0b7c30b2c0d6801be46bc61b3f22f60975e8397973a321268bbf302f4bcb65ab24
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
## Current
|
2
2
|
|
3
|
+
## Release v1.3.4 (10 August 2024)
|
4
|
+
|
5
|
+
* (#1060) Fix bug with return value of `Concurrent.available_processor_count` when `cpu.cfs_quota_us` is -1.
|
6
|
+
* (#1058) Add `Concurrent.cpu_shares` that is cgroups aware.
|
7
|
+
|
8
|
+
## Release v1.3.3 (9 June 2024)
|
9
|
+
|
10
|
+
* (#1053) Improve the speed of `Concurrent.physical_processor_count` on Windows.
|
11
|
+
|
12
|
+
## Release v1.3.2, edge v0.7.1 (7 June 2024)
|
13
|
+
|
14
|
+
concurrent-ruby:
|
15
|
+
|
16
|
+
* (#1051) Remove dependency on `win32ole`.
|
17
|
+
|
18
|
+
concurrent-ruby-edge:
|
19
|
+
|
20
|
+
* (#1052) Fix dependency on `concurrent-ruby` to allow the latest release.
|
21
|
+
|
3
22
|
## Release v1.3.1 (29 May 2024)
|
4
23
|
|
5
24
|
* Release 1.3.0 was broken when pushed to RubyGems. 1.3.1 is a packaging fix.
|
@@ -7,7 +26,7 @@
|
|
7
26
|
## Release v1.3.0 (28 May 2024)
|
8
27
|
|
9
28
|
* (#1042) Align Java Executor Service behavior for `shuttingdown?`, `shutdown?`
|
10
|
-
* (#1038) Add `Concurrent.
|
29
|
+
* (#1038) Add `Concurrent.available_processor_count` that is cgroups aware.
|
11
30
|
|
12
31
|
## Release v1.2.3 (16 Jan 2024)
|
13
32
|
|
data/Gemfile
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
version = File.read("#{__dir__}/lib/concurrent-ruby/concurrent/version.rb")[/'(.+)'/, 1] or raise
|
4
|
+
edge_version = File.read("#{__dir__}/lib/concurrent-ruby-edge/concurrent/edge/version.rb")[/'(.+)'/, 1] or raise
|
5
5
|
|
6
6
|
no_path = ENV['NO_PATH']
|
7
7
|
options = no_path ? {} : { path: '.' }
|
8
8
|
|
9
|
-
gem 'concurrent-ruby',
|
10
|
-
gem 'concurrent-ruby-edge',
|
11
|
-
gem 'concurrent-ruby-ext',
|
9
|
+
gem 'concurrent-ruby', version, options
|
10
|
+
gem 'concurrent-ruby-edge', edge_version, options
|
11
|
+
gem 'concurrent-ruby-ext', version, options.merge(platform: :mri)
|
12
12
|
|
13
13
|
group :development do
|
14
14
|
gem 'rake', '~> 13.0'
|
data/Rakefile
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require_relative 'lib/concurrent-ruby/concurrent/utility/engine'
|
1
|
+
version = File.read("#{__dir__}/lib/concurrent-ruby/concurrent/version.rb")[/'(.+)'/, 1] or raise
|
2
|
+
edge_version = File.read("#{__dir__}/lib/concurrent-ruby-edge/concurrent/edge/version.rb")[/'(.+)'/, 1] or raise
|
4
3
|
|
5
4
|
core_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby.gemspec')
|
6
5
|
ext_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-ext.gemspec')
|
@@ -8,14 +7,14 @@ edge_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-edge.
|
|
8
7
|
|
9
8
|
require 'rake/javaextensiontask'
|
10
9
|
|
11
|
-
ENV['JRUBY_HOME'] = ENV['CONCURRENT_JRUBY_HOME'] if ENV['CONCURRENT_JRUBY_HOME'] &&
|
10
|
+
ENV['JRUBY_HOME'] = ENV['CONCURRENT_JRUBY_HOME'] if ENV['CONCURRENT_JRUBY_HOME'] && RUBY_ENGINE != 'jruby'
|
12
11
|
|
13
12
|
Rake::JavaExtensionTask.new('concurrent_ruby', core_gemspec) do |ext|
|
14
13
|
ext.ext_dir = 'ext/concurrent-ruby'
|
15
14
|
ext.lib_dir = 'lib/concurrent-ruby/concurrent'
|
16
15
|
end
|
17
16
|
|
18
|
-
|
17
|
+
if RUBY_ENGINE == 'ruby'
|
19
18
|
require 'rake/extensiontask'
|
20
19
|
|
21
20
|
Rake::ExtensionTask.new('concurrent_ruby_ext', ext_gemspec) do |ext|
|
@@ -28,6 +27,10 @@ unless Concurrent.on_jruby? || Concurrent.on_truffleruby?
|
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
30
|
+
def which?(executable)
|
31
|
+
!`which #{executable} 2>/dev/null`.empty?
|
32
|
+
end
|
33
|
+
|
31
34
|
require 'rake_compiler_dock'
|
32
35
|
namespace :repackage do
|
33
36
|
desc '* with Windows fat distributions'
|
@@ -42,12 +45,19 @@ namespace :repackage do
|
|
42
45
|
Rake::Task['lib/concurrent-ruby/concurrent/concurrent_ruby.jar'].invoke
|
43
46
|
|
44
47
|
# build all gem files
|
48
|
+
rack_compiler_dock_kwargs = {}
|
49
|
+
if which?('podman') and (!which?('docker') || `docker --version`.include?('podman'))
|
50
|
+
# podman and only podman available, so RakeCompilerDock will use podman, otherwise it uses docker
|
51
|
+
rack_compiler_dock_kwargs = {
|
52
|
+
options: ['--privileged'], # otherwise the directory in the image is empty
|
53
|
+
runas: false
|
54
|
+
}
|
55
|
+
end
|
45
56
|
%w[x86-mingw32 x64-mingw32].each do |plat|
|
46
57
|
RakeCompilerDock.sh(
|
47
58
|
"bundle install --local && bundle exec rake native:#{plat} gem --trace",
|
48
59
|
platform: plat,
|
49
|
-
|
50
|
-
runas: false)
|
60
|
+
**rack_compiler_dock_kwargs)
|
51
61
|
end
|
52
62
|
end
|
53
63
|
end
|
@@ -57,7 +67,7 @@ require 'rubygems'
|
|
57
67
|
require 'rubygems/package_task'
|
58
68
|
|
59
69
|
Gem::PackageTask.new(core_gemspec) {} if core_gemspec
|
60
|
-
Gem::PackageTask.new(ext_gemspec) {} if ext_gemspec &&
|
70
|
+
Gem::PackageTask.new(ext_gemspec) {} if ext_gemspec && RUBY_ENGINE != 'jruby'
|
61
71
|
Gem::PackageTask.new(edge_gemspec) {} if edge_gemspec
|
62
72
|
|
63
73
|
CLEAN.include(
|
@@ -85,9 +95,9 @@ begin
|
|
85
95
|
task :installed do
|
86
96
|
Bundler.with_original_env do
|
87
97
|
Dir.chdir(__dir__) do
|
88
|
-
sh "gem install pkg/concurrent-ruby-#{
|
89
|
-
sh "gem install pkg/concurrent-ruby-ext-#{
|
90
|
-
sh "gem install pkg/concurrent-ruby-edge-#{
|
98
|
+
sh "gem install pkg/concurrent-ruby-#{version}.gem"
|
99
|
+
sh "gem install pkg/concurrent-ruby-ext-#{version}.gem" if RUBY_ENGINE == 'ruby'
|
100
|
+
sh "gem install pkg/concurrent-ruby-edge-#{edge_version}.gem"
|
91
101
|
ENV['NO_PATH'] = 'true'
|
92
102
|
sh 'bundle update'
|
93
103
|
sh 'bundle exec rake spec:ci'
|
@@ -117,7 +127,7 @@ rescue LoadError => e
|
|
117
127
|
puts 'RSpec is not installed, skipping test task definitions: ' + e.message
|
118
128
|
end
|
119
129
|
|
120
|
-
current_yard_version_name =
|
130
|
+
current_yard_version_name = version
|
121
131
|
|
122
132
|
begin
|
123
133
|
require 'yard'
|
@@ -221,6 +231,8 @@ namespace :release do
|
|
221
231
|
# Depends on environment of @pitr-ch
|
222
232
|
|
223
233
|
task :checks do
|
234
|
+
raise '$CONCURRENT_JRUBY_HOME must be set' unless ENV['CONCURRENT_JRUBY_HOME']
|
235
|
+
|
224
236
|
Dir.chdir(__dir__) do
|
225
237
|
sh 'test -z "$(git status --porcelain)"' do |ok, res|
|
226
238
|
unless ok
|
@@ -251,15 +263,19 @@ namespace :release do
|
|
251
263
|
|
252
264
|
desc '* test actual installed gems instead of cloned repository on MRI and JRuby'
|
253
265
|
task :test do
|
266
|
+
raise '$CONCURRENT_JRUBY_HOME must be set' unless ENV['CONCURRENT_JRUBY_HOME']
|
267
|
+
|
254
268
|
Dir.chdir(__dir__) do
|
255
269
|
puts "Testing with the installed gem"
|
256
270
|
|
257
271
|
Bundler.with_original_env do
|
258
272
|
sh 'ruby -v'
|
273
|
+
sh 'bundle install'
|
259
274
|
sh 'bundle exec rake spec:installed'
|
260
275
|
|
261
|
-
env = { "PATH" => "#{ENV
|
276
|
+
env = { "PATH" => "#{ENV.fetch('CONCURRENT_JRUBY_HOME')}/bin:#{ENV['PATH']}" }
|
262
277
|
sh env, 'ruby -v'
|
278
|
+
sh env, 'bundle install'
|
263
279
|
sh env, 'bundle exec rake spec:installed'
|
264
280
|
end
|
265
281
|
|
@@ -271,8 +287,8 @@ namespace :release do
|
|
271
287
|
task :publish => ['publish:ask', 'publish:tag', 'publish:rubygems', 'publish:post_steps']
|
272
288
|
|
273
289
|
namespace :publish do
|
274
|
-
publish_base =
|
275
|
-
publish_edge =
|
290
|
+
publish_base = nil
|
291
|
+
publish_edge = nil
|
276
292
|
|
277
293
|
task :ask do
|
278
294
|
begin
|
@@ -280,8 +296,15 @@ namespace :release do
|
|
280
296
|
input = STDIN.gets.strip.downcase
|
281
297
|
end until %w(y n).include?(input)
|
282
298
|
exit 1 if input == 'n'
|
299
|
+
|
300
|
+
begin
|
301
|
+
STDOUT.puts 'Do you want to publish `concurrent-ruby`? (y/n)'
|
302
|
+
input = STDIN.gets.strip.downcase
|
303
|
+
end until %w(y n).include?(input)
|
304
|
+
publish_base = input == 'y'
|
305
|
+
|
283
306
|
begin
|
284
|
-
STDOUT.puts '
|
307
|
+
STDOUT.puts 'Do you want to publish `concurrent-ruby-edge`? (y/n)'
|
285
308
|
input = STDIN.gets.strip.downcase
|
286
309
|
end until %w(y n).include?(input)
|
287
310
|
publish_edge = input == 'y'
|
@@ -290,21 +313,21 @@ namespace :release do
|
|
290
313
|
desc '** tag HEAD with current version and push to github'
|
291
314
|
task :tag => :ask do
|
292
315
|
Dir.chdir(__dir__) do
|
293
|
-
sh "git tag v#{
|
294
|
-
sh "git push origin v#{
|
295
|
-
sh "git tag edge-v#{
|
296
|
-
sh "git push origin edge-v#{
|
316
|
+
sh "git tag v#{version}" if publish_base
|
317
|
+
sh "git push origin v#{version}" if publish_base
|
318
|
+
sh "git tag edge-v#{edge_version}" if publish_edge
|
319
|
+
sh "git push origin edge-v#{edge_version}" if publish_edge
|
297
320
|
end
|
298
321
|
end
|
299
322
|
|
300
323
|
desc '** push all *.gem files to rubygems'
|
301
324
|
task :rubygems => :ask do
|
302
325
|
Dir.chdir(__dir__) do
|
303
|
-
sh "gem push pkg/concurrent-ruby-#{
|
304
|
-
sh "gem push pkg/concurrent-ruby-edge-#{
|
305
|
-
sh "gem push pkg/concurrent-ruby-ext-#{
|
306
|
-
sh "gem push pkg/concurrent-ruby-ext-#{
|
307
|
-
sh "gem push pkg/concurrent-ruby-ext-#{
|
326
|
+
sh "gem push pkg/concurrent-ruby-#{version}.gem" if publish_base
|
327
|
+
sh "gem push pkg/concurrent-ruby-edge-#{edge_version}.gem" if publish_edge
|
328
|
+
sh "gem push pkg/concurrent-ruby-ext-#{version}.gem" if publish_base
|
329
|
+
sh "gem push pkg/concurrent-ruby-ext-#{version}-x64-mingw32.gem" if publish_base
|
330
|
+
sh "gem push pkg/concurrent-ruby-ext-#{version}-x86-mingw32.gem" if publish_base
|
308
331
|
end
|
309
332
|
end
|
310
333
|
|
Binary file
|
@@ -12,6 +12,7 @@ module Concurrent
|
|
12
12
|
@processor_count = Delay.new { compute_processor_count }
|
13
13
|
@physical_processor_count = Delay.new { compute_physical_processor_count }
|
14
14
|
@cpu_quota = Delay.new { compute_cpu_quota }
|
15
|
+
@cpu_shares = Delay.new { compute_cpu_shares }
|
15
16
|
end
|
16
17
|
|
17
18
|
def processor_count
|
@@ -41,6 +42,10 @@ module Concurrent
|
|
41
42
|
@cpu_quota.value
|
42
43
|
end
|
43
44
|
|
45
|
+
def cpu_shares
|
46
|
+
@cpu_shares.value
|
47
|
+
end
|
48
|
+
|
44
49
|
private
|
45
50
|
|
46
51
|
def compute_processor_count
|
@@ -68,10 +73,20 @@ module Concurrent
|
|
68
73
|
end
|
69
74
|
cores.count
|
70
75
|
when /mswin|mingw/
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
76
|
+
# 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
|
77
|
+
result = run('powershell -command "Get-CimInstance -ClassName Win32_Processor -Property NumberOfCores | Select-Object -Property NumberOfCores"')
|
78
|
+
if !result || $?.exitstatus != 0
|
79
|
+
# fallback to deprecated wmic for older systems
|
80
|
+
result = run("wmic cpu get NumberOfCores")
|
81
|
+
end
|
82
|
+
if !result || $?.exitstatus != 0
|
83
|
+
# Bail out if both commands returned something unexpected
|
84
|
+
processor_count
|
85
|
+
else
|
86
|
+
# powershell: "\nNumberOfCores\n-------------\n 4\n\n\n"
|
87
|
+
# wmic: "NumberOfCores \n\n4 \n\n\n\n"
|
88
|
+
result.scan(/\d+/).map(&:to_i).reduce(:+)
|
89
|
+
end
|
75
90
|
else
|
76
91
|
processor_count
|
77
92
|
end
|
@@ -81,6 +96,11 @@ module Concurrent
|
|
81
96
|
return 1
|
82
97
|
end
|
83
98
|
|
99
|
+
def run(command)
|
100
|
+
IO.popen(command, &:read)
|
101
|
+
rescue Errno::ENOENT
|
102
|
+
end
|
103
|
+
|
84
104
|
def compute_cpu_quota
|
85
105
|
if RbConfig::CONFIG["target_os"].include?("linux")
|
86
106
|
if File.exist?("/sys/fs/cgroup/cpu.max")
|
@@ -92,12 +112,28 @@ module Concurrent
|
|
92
112
|
elsif File.exist?("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us")
|
93
113
|
# cgroups v1: https://kernel.googlesource.com/pub/scm/linux/kernel/git/glommer/memcg/+/cpu_stat/Documentation/cgroups/cpu.txt
|
94
114
|
max = File.read("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us").to_i
|
95
|
-
|
115
|
+
# If the cpu.cfs_quota_us is -1, cgroup does not adhere to any CPU time restrictions
|
116
|
+
# https://docs.kernel.org/scheduler/sched-bwc.html#management
|
117
|
+
return nil if max <= 0
|
96
118
|
period = File.read("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us").to_f
|
97
119
|
max / period
|
98
120
|
end
|
99
121
|
end
|
100
122
|
end
|
123
|
+
|
124
|
+
def compute_cpu_shares
|
125
|
+
if RbConfig::CONFIG["target_os"].include?("linux")
|
126
|
+
if File.exist?("/sys/fs/cgroup/cpu.weight")
|
127
|
+
# cgroups v2: https://docs.kernel.org/admin-guide/cgroup-v2.html#cpu-interface-files
|
128
|
+
# Ref: https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2254-cgroup-v2#phase-1-convert-from-cgroups-v1-settings-to-v2
|
129
|
+
weight = File.read("/sys/fs/cgroup/cpu.weight").to_f
|
130
|
+
((((weight - 1) * 262142) / 9999) + 2) / 1024
|
131
|
+
elsif File.exist?("/sys/fs/cgroup/cpu/cpu.shares")
|
132
|
+
# cgroups v1: https://kernel.googlesource.com/pub/scm/linux/kernel/git/glommer/memcg/+/cpu_stat/Documentation/cgroups/cpu.txt
|
133
|
+
File.read("/sys/fs/cgroup/cpu/cpu.shares").to_f / 1024
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
101
137
|
end
|
102
138
|
end
|
103
139
|
|
@@ -113,8 +149,8 @@ module Concurrent
|
|
113
149
|
# `java.lang.Runtime.getRuntime.availableProcessors` will be used. According
|
114
150
|
# to the Java documentation this "value may change during a particular
|
115
151
|
# invocation of the virtual machine... [applications] should therefore
|
116
|
-
# occasionally poll this property."
|
117
|
-
#
|
152
|
+
# occasionally poll this property." We still memoize this value once under
|
153
|
+
# JRuby.
|
118
154
|
#
|
119
155
|
# Otherwise Ruby's Etc.nprocessors will be used.
|
120
156
|
#
|
@@ -147,13 +183,14 @@ module Concurrent
|
|
147
183
|
end
|
148
184
|
|
149
185
|
# Number of processors cores available for process scheduling.
|
150
|
-
#
|
151
|
-
#
|
186
|
+
# This method takes in account the CPU quota if the process is inside a cgroup with a
|
187
|
+
# dedicated CPU quota (typically Docker).
|
188
|
+
# Otherwise it returns the same value as #processor_count but as a Float.
|
152
189
|
#
|
153
190
|
# For performance reasons the calculated value will be memoized on the first
|
154
191
|
# call.
|
155
192
|
#
|
156
|
-
# @return [
|
193
|
+
# @return [Float] number of available processors
|
157
194
|
def self.available_processor_count
|
158
195
|
processor_counter.available_processor_count
|
159
196
|
end
|
@@ -172,4 +209,12 @@ module Concurrent
|
|
172
209
|
def self.cpu_quota
|
173
210
|
processor_counter.cpu_quota
|
174
211
|
end
|
212
|
+
|
213
|
+
# The CPU shares requested by the process. For performance reasons the calculated
|
214
|
+
# value will be memoized on the first call.
|
215
|
+
#
|
216
|
+
# @return [Float, nil] CPU shares requested by the process, or nil if not set
|
217
|
+
def self.cpu_shares
|
218
|
+
processor_counter.cpu_shares
|
219
|
+
end
|
175
220
|
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.3.
|
4
|
+
version: 1.3.4
|
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-
|
13
|
+
date: 2024-08-10 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.
|