bootsnap 1.18.4 → 1.18.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b2271b2fa08edc313e43ec1359be530fcb6b206a7b4b63f37065290289cbc9a
4
- data.tar.gz: c5838e7d01c33320e765a2bf668c68c09fc6b0938fb8789653b526cb3c22a244
3
+ metadata.gz: 49e48977ddbf373c70db5988627366223140c8718fcf36cc4dd55d82a20716d4
4
+ data.tar.gz: 23b7644313a2c0d2df0a2b6c3816a1634a2f3f94f8c12388c6b674608b92aa82
5
5
  SHA512:
6
- metadata.gz: 77168e700a54163bf4574fbf9f82fea681a01f7d0c5c3a55340d3dabc98959fce1176bebef4c4d25d18efa257ad5314f13ca978a77f5cb4288296c63a1b36871
7
- data.tar.gz: cc770950cc3032a5033873457a23b19823c35d9d24285f3b13fb95848e51d8f34defca5396c7b545b5530381271979c93026401e4ac32d28ec0f89ceadd57823
6
+ metadata.gz: e50126e1a8a1cfa22cee67fc04efd056a2f792a0aee08cbd73ff0a7e5cec0e8f2902b0ddc08a89a3d2a12c119bf042290acd0ec28642c5c6acc86adaa317ef31
7
+ data.tar.gz: cc8c691e916b5df79c073d0285154df4c3483c09b6fe085d2bde5ff11e1e710a01b68d86db3bbfd253b3cce95b278720e47f94e8989941c899bb80d4a3e7151e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Unreleased
2
2
 
3
+ # 1.18.5
4
+
5
+ * Attempt to detect a QEMU bug that can cause `bootsnap precompile` to hang forever when building ARM64 docker images
6
+ from x86_64 machines. See #495.
7
+ * Improve CLI to detect cgroup CPU limits and avoid spawning too many worker processes.
8
+
3
9
  # 1.18.4
4
10
 
5
11
  * Allow using bootsnap without bundler. See #488.
data/README.md CHANGED
@@ -188,7 +188,7 @@ result too, raising a `LoadError` without touching the filesystem at all.
188
188
 
189
189
  Ruby has complex grammar and parsing it is not a particularly cheap operation. Since 1.9, Ruby has
190
190
  translated ruby source to an internal bytecode format, which is then executed by the Ruby VM. Since
191
- 2.3.0, Ruby [exposes an API](https://ruby-doc.org/core-2.3.0/RubyVM/InstructionSequence.html) that
191
+ 2.3.0, Ruby [exposes an API](https://docs.ruby-lang.org/en/master/RubyVM/InstructionSequence.html) that
192
192
  allows caching that bytecode. This allows us to bypass the relatively-expensive compilation step on
193
193
  subsequent loads of the same file.
194
194
 
@@ -331,7 +331,7 @@ To do so you can use the `bootsnap precompile` command.
331
331
  Example:
332
332
 
333
333
  ```bash
334
- $ bundle exec bootsnap precompile --gemfile app/ lib/
334
+ $ bundle exec bootsnap precompile --gemfile app/ lib/ config/
335
335
  ```
336
336
 
337
337
  ## When not to use Bootsnap
@@ -1,16 +1,88 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "etc"
4
+ require "rbconfig"
5
+ require "io/wait" unless IO.method_defined?(:wait_readable)
6
+
3
7
  module Bootsnap
4
8
  class CLI
5
9
  class WorkerPool
6
10
  class << self
7
11
  def create(size:, jobs:)
12
+ size ||= default_size
8
13
  if size > 0 && Process.respond_to?(:fork)
9
14
  new(size: size, jobs: jobs)
10
15
  else
11
16
  Inline.new(jobs: jobs)
12
17
  end
13
18
  end
19
+
20
+ def default_size
21
+ nprocessors = Etc.nprocessors
22
+ size = [nprocessors, cpu_quota || nprocessors].min
23
+ case size
24
+ when 0, 1
25
+ 0
26
+ else
27
+ if fork_defunct?
28
+ $stderr.puts "warning: faulty fork(2) detected, probably in cross platform docker builds. " \
29
+ "Disabling parallel compilation."
30
+ 0
31
+ else
32
+ size
33
+ end
34
+ end
35
+ end
36
+
37
+ def cpu_quota
38
+ if RbConfig::CONFIG["target_os"].include?("linux")
39
+ if File.exist?("/sys/fs/cgroup/cpu.max")
40
+ # cgroups v2: https://docs.kernel.org/admin-guide/cgroup-v2.html#cpu-interface-files
41
+ cpu_max = File.read("/sys/fs/cgroup/cpu.max")
42
+ return nil if cpu_max.start_with?("max ") # no limit
43
+
44
+ max, period = cpu_max.split.map(&:to_f)
45
+ max / period
46
+ elsif File.exist?("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us")
47
+ # cgroups v1: https://kernel.googlesource.com/pub/scm/linux/kernel/git/glommer/memcg/+/cpu_stat/Documentation/cgroups/cpu.txt
48
+ max = File.read("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us").to_i
49
+ # If the cpu.cfs_quota_us is -1, cgroup does not adhere to any CPU time restrictions
50
+ # https://docs.kernel.org/scheduler/sched-bwc.html#management
51
+ return nil if max <= 0
52
+
53
+ period = File.read("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us").to_f
54
+ max / period
55
+ end
56
+ end
57
+ end
58
+
59
+ def fork_defunct?
60
+ return true unless ::Process.respond_to?(:fork)
61
+
62
+ # Ref: https://github.com/Shopify/bootsnap/issues/495
63
+ # The second forked process will hang on some QEMU environments
64
+ r, w = IO.pipe
65
+ pids = 2.times.map do
66
+ ::Process.fork do
67
+ exit!(true)
68
+ end
69
+ end
70
+ w.close
71
+ r.wait_readable(1) # Wait at most 1s
72
+
73
+ defunct = false
74
+
75
+ pids.each do |pid|
76
+ _pid, status = ::Process.wait2(pid, ::Process::WNOHANG)
77
+ if status.nil? # Didn't exit in 1s
78
+ defunct = true
79
+ Process.kill(:KILL, pid)
80
+ ::Process.wait2(pid)
81
+ end
82
+ end
83
+
84
+ defunct
85
+ end
14
86
  end
15
87
 
16
88
  class Inline
data/lib/bootsnap/cli.rb CHANGED
@@ -4,7 +4,6 @@ require "bootsnap"
4
4
  require "bootsnap/cli/worker_pool"
5
5
  require "optparse"
6
6
  require "fileutils"
7
- require "etc"
8
7
 
9
8
  module Bootsnap
10
9
  class CLI
@@ -29,7 +28,7 @@ module Bootsnap
29
28
  self.compile_gemfile = false
30
29
  self.exclude = nil
31
30
  self.verbose = false
32
- self.jobs = Etc.nprocessors
31
+ self.jobs = nil
33
32
  self.iseq = true
34
33
  self.yaml = true
35
34
  self.json = true
@@ -142,7 +142,7 @@ module Bootsnap
142
142
  # will _never_ run on MacOS, and therefore think they can get away
143
143
  # with calling a Ruby file 'x.dylib.rb' and then requiring it as 'x.dylib'.)
144
144
  #
145
- # See <https://ruby-doc.org/core-2.6.4/Kernel.html#method-i-require>.
145
+ # See <https://docs.ruby-lang.org/en/master/Kernel.html#method-i-require>.
146
146
  def extension_elidable?(feature)
147
147
  feature.to_s.end_with?(".rb", ".so", ".o", ".dll", ".dylib")
148
148
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bootsnap
4
- VERSION = "1.18.4"
4
+ VERSION = "1.18.5"
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootsnap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.18.4
4
+ version: 1.18.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Burke Libbey
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-08-05 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: msgpack
@@ -68,7 +67,6 @@ metadata:
68
67
  changelog_uri: https://github.com/Shopify/bootsnap/blob/main/CHANGELOG.md
69
68
  source_code_uri: https://github.com/Shopify/bootsnap
70
69
  allowed_push_host: https://rubygems.org
71
- post_install_message:
72
70
  rdoc_options: []
73
71
  require_paths:
74
72
  - lib
@@ -83,8 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
81
  - !ruby/object:Gem::Version
84
82
  version: '0'
85
83
  requirements: []
86
- rubygems_version: 3.5.16
87
- signing_key:
84
+ rubygems_version: 3.6.8
88
85
  specification_version: 4
89
86
  summary: Boot large ruby/rails apps faster
90
87
  test_files: []