From 7fea31ddc0afd962f319494076be3d633557952f 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. --- CHANGELOG.md | 2 ++ .../concurrent/utility/processor_counter.rb | 4 +++- spec/concurrent/utility/processor_count_spec.rb | 9 +++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c117834d4..32261d239 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## Current +* (#1060) Fix bug with return value of `Concurrent.available_processor_count` when `cpu.cfs_quota_us` is -1. + ## Release v1.3.3 (9 June 2024) * (#1053) Improve the speed of `Concurrent.physical_processor_count` on Windows. diff --git a/lib/concurrent-ruby/concurrent/utility/processor_counter.rb b/lib/concurrent-ruby/concurrent/utility/processor_counter.rb index 5a2db24f3..2489cbd76 100644 --- a/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +++ b/lib/concurrent-ruby/concurrent/utility/processor_counter.rb @@ -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 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 7a636640c..8de31e027 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)