Skip to content

Commit 5e87800

Browse files
committed
cli: improve automatic parallelism to respect cgroup limits
1 parent 0dc269d commit 5e87800

File tree

3 files changed

+37
-2
lines changed

3 files changed

+37
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Unreleased
22

3+
* Improve CLI to detect cgroup CPU limits and avoid spawning too many worker processes.
4+
35
# 1.18.4
46

57
* Allow using bootsnap without bundler. See #488.

lib/bootsnap/cli.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
require "bootsnap/cli/worker_pool"
55
require "optparse"
66
require "fileutils"
7-
require "etc"
87

98
module Bootsnap
109
class CLI
@@ -29,7 +28,7 @@ def initialize(argv)
2928
self.compile_gemfile = false
3029
self.exclude = nil
3130
self.verbose = false
32-
self.jobs = Etc.nprocessors
31+
self.jobs = nil
3332
self.iseq = true
3433
self.yaml = true
3534
self.json = true

lib/bootsnap/cli/worker_pool.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,50 @@
11
# frozen_string_literal: true
22

3+
require "etc"
4+
require "rbconfig"
5+
36
module Bootsnap
47
class CLI
58
class WorkerPool
69
class << self
710
def create(size:, jobs:)
11+
size ||= default_size
812
if size > 0 && Process.respond_to?(:fork)
913
new(size: size, jobs: jobs)
1014
else
1115
Inline.new(jobs: jobs)
1216
end
1317
end
18+
19+
def default_size
20+
size = [Etc.nprocessors, cpu_quota || 0].min
21+
case size
22+
when 0, 1
23+
0
24+
else
25+
size
26+
end
27+
end
28+
29+
def cpu_quota
30+
if RbConfig::CONFIG["target_os"].include?("linux")
31+
if File.exist?("/sys/fs/cgroup/cpu.max")
32+
# cgroups v2: https://docs.kernel.org/admin-guide/cgroup-v2.html#cpu-interface-files
33+
cpu_max = File.read("/sys/fs/cgroup/cpu.max")
34+
return nil if cpu_max.start_with?("max ") # no limit
35+
max, period = cpu_max.split.map(&:to_f)
36+
max / period
37+
elsif File.exist?("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us")
38+
# cgroups v1: https://kernel.googlesource.com/pub/scm/linux/kernel/git/glommer/memcg/+/cpu_stat/Documentation/cgroups/cpu.txt
39+
max = File.read("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us").to_i
40+
# If the cpu.cfs_quota_us is -1, cgroup does not adhere to any CPU time restrictions
41+
# https://docs.kernel.org/scheduler/sched-bwc.html#management
42+
return nil if max <= 0
43+
period = File.read("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us").to_f
44+
max / period
45+
end
46+
end
47+
end
1448
end
1549

1650
class Inline

0 commit comments

Comments
 (0)