concurrent-ruby 1.2.1 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -60,6 +80,24 @@ module Concurrent
60
80
  rescue
61
81
  return 1
62
82
  end
83
+
84
+ def compute_cpu_quota
85
+ if RbConfig::CONFIG["target_os"].include?("linux")
86
+ if File.exist?("/sys/fs/cgroup/cpu.max")
87
+ # cgroups v2: https://docs.kernel.org/admin-guide/cgroup-v2.html#cpu-interface-files
88
+ cpu_max = File.read("/sys/fs/cgroup/cpu.max")
89
+ return nil if cpu_max.start_with?("max ") # no limit
90
+ max, period = cpu_max.split.map(&:to_f)
91
+ max / period
92
+ elsif File.exist?("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us")
93
+ # cgroups v1: https://kernel.googlesource.com/pub/scm/linux/kernel/git/glommer/memcg/+/cpu_stat/Documentation/cgroups/cpu.txt
94
+ max = File.read("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us").to_i
95
+ return nil if max == 0
96
+ period = File.read("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us").to_f
97
+ max / period
98
+ end
99
+ end
100
+ end
63
101
  end
64
102
  end
65
103
 
@@ -107,4 +145,31 @@ module Concurrent
107
145
  def self.physical_processor_count
108
146
  processor_counter.physical_processor_count
109
147
  end
148
+
149
+ # Number of processors cores available for process scheduling.
150
+ # Returns `nil` if there is no #cpu_quota, or a `Float` if the
151
+ # process is inside a cgroup with a dedicated CPU quota (typically Docker).
152
+ #
153
+ # For performance reasons the calculated value will be memoized on the first
154
+ # call.
155
+ #
156
+ # @return [nil, Float] number of available processors
157
+ def self.available_processor_count
158
+ processor_counter.available_processor_count
159
+ end
160
+
161
+ # The maximum number of processors cores available for process scheduling.
162
+ # Returns `nil` if there is no enforced limit, or a `Float` if the
163
+ # process is inside a cgroup with a dedicated CPU quota (typically Docker).
164
+ #
165
+ # Note that nothing prevents setting a CPU quota higher than the actual number of
166
+ # cores on the system.
167
+ #
168
+ # For performance reasons the calculated value will be memoized on the first
169
+ # call.
170
+ #
171
+ # @return [nil, Float] Maximum number of available processors as set by a cgroup CPU quota, or nil if none set
172
+ def self.cpu_quota
173
+ processor_counter.cpu_quota
174
+ end
110
175
  end
@@ -1,3 +1,3 @@
1
1
  module Concurrent
2
- VERSION = '1.2.1'
2
+ VERSION = '1.3.1'
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.1
4
+ version: 1.3.1
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: 2023-02-24 00:00:00.000000000 Z
13
+ date: 2024-05-29 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.
@@ -76,7 +76,6 @@ files:
76
76
  - lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb
77
77
  - lib/concurrent-ruby/concurrent/collection/java_non_concurrent_priority_queue.rb
78
78
  - lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb
79
- - lib/concurrent-ruby/concurrent/collection/map/atomic_reference_map_backend.rb
80
79
  - lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb
81
80
  - lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb
82
81
  - lib/concurrent-ruby/concurrent/collection/map/synchronized_map_backend.rb
@@ -147,7 +146,6 @@ files:
147
146
  - lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb
148
147
  - lib/concurrent-ruby/concurrent/thread_safe/util.rb
149
148
  - lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb
150
- - lib/concurrent-ruby/concurrent/thread_safe/util/cheap_lockable.rb
151
149
  - lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb
152
150
  - lib/concurrent-ruby/concurrent/thread_safe/util/power_of_two_tuple.rb
153
151
  - lib/concurrent-ruby/concurrent/thread_safe/util/striped64.rb