From ddf62f6aa8d32ce6406ed0b7c12ffc9c19a2031d Mon Sep 17 00:00:00 2001 From: Yuji Yaginuma Date: Fri, 9 Aug 2024 12:30:47 +0900 Subject: [PATCH] Fix the return value of `Concurrent.available_processor_count` when `cpu.cfs_quota_us` is -1 I tried to use `Concurrent.available_processor_count` in `parallel` gem, but we got some feedback `Concurrent.available_processor_count` returned a negative value. https://github.com/grosser/parallel/pull/348#issuecomment-2275859126 https://github.com/grosser/parallel/issues/349#issuecomment-2275953547 According to the https://docs.kernel.org/scheduler/sched-bwc.html#management, The default value of `cpu.cfs_quota_us` is -1. In that case, cgroup does not adhere to any CPU time restrictions. This PR adds the case of `cpu.cfs_quota_us` is -1 to `#cpu_quota` to return processor count from `Concurrent.available_processor_count` in that case. --- .../concurrent/utility/processor_counter.rb | 6 ++++-- spec/concurrent/utility/processor_count_spec.rb | 9 +++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/concurrent-ruby/concurrent/utility/processor_counter.rb b/lib/concurrent-ruby/concurrent/utility/processor_counter.rb index 2dd91b59..5efdd016 100644 --- a/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +++ b/lib/concurrent-ruby/concurrent/utility/processor_counter.rb @@ -83,7 +83,7 @@ def compute_physical_processor_count # Bail out if both commands returned something unexpected processor_count else - # powershell: "\nNumberOfCores\n-------------\n 4\n\n\n" + # powershell: "\nNumberOfCores\n-------------\n 4\n\n\n" # wmic: "NumberOfCores \n\n4 \n\n\n\n" result.scan(/\d+/).map(&:to_i).reduce(:+) end @@ -112,7 +112,9 @@ def compute_cpu_quota elsif File.exist?("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us") # cgroups v1: https://kernel.googlesource.com/pub/scm/linux/kernel/git/glommer/memcg/+/cpu_stat/Documentation/cgroups/cpu.txt max = File.read("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us").to_i - return nil if max == 0 + # If the cpu.cfs_quota_us is -1, cgroup does not adhere to any CPU time restrictions + # https://docs.kernel.org/scheduler/sched-bwc.html#management + return nil if max == 0 || max == -1 period = File.read("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us").to_f max / period end diff --git a/spec/concurrent/utility/processor_count_spec.rb b/spec/concurrent/utility/processor_count_spec.rb index 7a636640..8de31e02 100644 --- a/spec/concurrent/utility/processor_count_spec.rb +++ b/spec/concurrent/utility/processor_count_spec.rb @@ -56,6 +56,15 @@ module Concurrent expect(counter.cpu_quota).to be_nil end + it 'returns nil if cgroups v1 and cpu.cfs_quota_us is -1' do + expect(RbConfig::CONFIG).to receive(:[]).with("target_os").and_return("linux") + expect(File).to receive(:exist?).with("/sys/fs/cgroup/cpu.max").and_return(false) + expect(File).to receive(:exist?).with("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us").and_return(true) + + expect(File).to receive(:read).with("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us").and_return("-1\n") + expect(counter.cpu_quota).to be_nil + end + it 'returns a float if cgroups v1 sets a limit' do expect(RbConfig::CONFIG).to receive(:[]).with("target_os").and_return("linux") expect(File).to receive(:exist?).with("/sys/fs/cgroup/cpu.max").and_return(false)