bootsnap 1.6.0 → 1.18.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '029d63ba428f470d2cd2ef194d857e20689e7c8e377e2eaaaab83570f366034a'
4
- data.tar.gz: 36a55f9d12dddef6ea3c4739f586c9236d7f4bc677a8b6747dfd7465d46eeca2
3
+ metadata.gz: 4fa4ab785277ee01a1c8ee75b43f0efb93db42bffcdacc1c8505a65efa03dede
4
+ data.tar.gz: 8aaaca48ae257b563580023c8fa36a59463f4c30f5463c14f6b8b94bf5fe27df
5
5
  SHA512:
6
- metadata.gz: 131ec17c4e4912f387c18778250e689467ebfcc80e91eb884237307af1a57a3c89d4fb20c772fbc0330123a796d631861a9cf145bd32c54183077bbc97d7fa6f
7
- data.tar.gz: d0c92454c8a5d8b16a25908fd0ae134fc817c5977958bde8424baca2bb6c96e60eb648c9f770bf7c7f58a3dd98871d4e7b0e3a0950c269100fded45ca9fddfa3
6
+ metadata.gz: 27b48d27d3330c8565952a2fbb979e71013b1e9585bcb3284656192808c304f2874c32a135b14895eec61a7ef038fa71fa111964a56e7aaedc9ff507ef307686
7
+ data.tar.gz: c3d83a0b068f2908a6298c7cd8e1a660f1228a7ddbfb9409cb3f6c174319f3974388ce73756c04062b17b97a37e199a07bccbb0b8dc1c6224998c58c51194b27
data/CHANGELOG.md CHANGED
@@ -1,5 +1,223 @@
1
1
  # Unreleased
2
2
 
3
+ # 1.18.3
4
+
5
+ * Fix the cache corruption issue in the revalidation feature. See #474.
6
+ The cache revalidation feature remains opt-in for now, until it is more battle tested.
7
+
8
+ # 1.18.2
9
+
10
+ * Disable stale cache entries revalidation by default as it seems to cause cache corruption issues. See #471 and #474.
11
+ Will be re-enabled in a future version once the root cause is identified.
12
+ * Fix a potential compilation issue on some systems. See #470.
13
+
14
+ # 1.18.1
15
+
16
+ * Handle `EPERM` errors when opening files with `O_NOATIME`.
17
+
18
+ # 1.18.0
19
+
20
+ * `Bootsnap.instrumentation` now receive `:hit` events.
21
+ * Add `Bootsnap.log_stats!` to print hit rate statistics on process exit. Can also be enabled with `BOOTSNAP_STATS=1`.
22
+ * Revalidate stale cache entries by digesting the source content.
23
+ This should significantly improve performance in environments where `mtime` isn't preserved (e.g. CI systems doing a git clone, etc).
24
+ See #468.
25
+ * Open source files and cache entries with `O_NOATIME` when available to reduce disk accesses. See #469.
26
+ * `bootsnap precompile --gemfile` now look for `.rb` files in the whole gem and not just the `lib/` directory. See #466.
27
+
28
+ # 1.17.1
29
+
30
+ * Fix a compatibility issue with the `prism` library that ships with Ruby 3.3. See #463.
31
+ * Improved the `Kernel#require` decorator to not cause a method redefinition warning. See #461.
32
+
33
+ # 1.17.0
34
+
35
+ * Ensure `$LOAD_PATH.dup` is Ractor shareable to fix an conflict with `did_you_mean`.
36
+ * Allow to ignore directories using absolute paths.
37
+ * Support YAML and JSON CompileCache on TruffleRuby.
38
+ * Support LoadPathCache on TruffleRuby.
39
+
40
+ # 1.16.0
41
+
42
+ * Use `RbConfig::CONFIG["rubylibdir"]` instead of `RbConfig::CONFIG["libdir"]` to check for stdlib files. See #431.
43
+ * Fix the cached version of `YAML.load_file` being slightly more permissive than the default `Psych` one. See #434.
44
+ `Date` and `Time` values are now properly rejected, as well as aliases.
45
+ If this causes a regression in your application, it is recommended to load *trusted* YAML files with `YAML.unsafe_load_file`.
46
+
47
+ # 1.15.0
48
+
49
+ * Add a readonly mode, for environments in which the updated cache wouldn't be persisted. See #428 and #423.
50
+
51
+ # 1.14.0
52
+
53
+ * Require Ruby 2.6.
54
+ * Add a way to skip directories during load path scanning.
55
+ If you have large non-ruby directories in the middle of your load path, it can severely slow down scanning.
56
+ Typically this is a problem with `node_modules`. See #277.
57
+ * Fix `Bootsnap.unload_cache!`, it simply wouldn't work at all because of a merge mistake. See #421.
58
+
59
+ # 1.13.0
60
+
61
+ * Stop decorating `Kernel.load`. This used to be very useful in development because the Rails "classic" autoloader
62
+ was using `Kernel.load` in dev and `Kernel.require` in production. But Zeitwerk is now the default, and it doesn't
63
+ use `Kernel.load` at all.
64
+
65
+ People still using the classic autoloader might want to stick to `bootsnap 1.12`.
66
+
67
+ * Add `Bootsnap.unload_cache!`. Applications can call it at the end of their boot sequence when they know
68
+ no more code will be loaded to reclaim a bit of memory.
69
+
70
+ # 1.12.0
71
+
72
+ * `bootsnap precompile` CLI will now also precompile `Rakefile` and `.rake` files.
73
+
74
+ * Stop decorating `Module#autoload` as it was only useful for supporting Ruby 2.2 and older.
75
+
76
+ * Remove `uname` and other platform specific version from the cache keys. `RUBY_PLATFORM + RUBY_REVISION` should be
77
+ enough to ensure bytecode compatibility. This should improve caching for alpine based setups. See #409.
78
+
79
+ # 1.11.1
80
+
81
+ * Fix the `can't modify frozen Hash` error on load path cache mutation. See #411.
82
+
83
+ # 1.11.0
84
+
85
+ * Drop dependency on `fileutils`.
86
+
87
+ * Better respect `Kernel#require` duck typing. While it almost never comes up in practice, `Kernel#require`
88
+ follow a fairly intricate duck-typing protocol on its argument implemented as `rb_get_path(VALUE)` in MRI.
89
+ So when applicable we bind `rb_get_path` and use it for improved compatibility. See #396 and #406.
90
+
91
+ * Get rid of the `Kernel.require_relative` decorator by resolving `$LOAD_PATH` members to their real path.
92
+ This way we handle symlinks in `$LOAD_PATH` much more efficiently. See #402 for the detailed explanation.
93
+
94
+ * Drop support for Ruby 2.3 (to allow getting rid of the `Kernel.require_relative` decorator).
95
+
96
+ # 1.10.3
97
+
98
+ * Fix Regexp and Date type support in YAML compile cache. (#400)
99
+
100
+ * Improve the YAML compile cache to support `UTF-8` symbols. (#398, #399)
101
+ [The default `MessagePack` symbol serializer assumes all symbols are ASCII](https://github.com/msgpack/msgpack-ruby/pull/211),
102
+ because of this, non-ASCII compatible symbol would be restored with `ASCII_8BIT` encoding (AKA `BINARY`).
103
+ Bootsnap now properly cache them in `UTF-8`.
104
+
105
+ Note that the above only apply for actual YAML symbols (e..g `--- :foo`).
106
+ The issue is still present for string keys parsed with `YAML.load_file(..., symbolize_names: true)`, that is a bug
107
+ in `msgpack` that will hopefully be solved soon, see: https://github.com/msgpack/msgpack-ruby/pull/246
108
+
109
+ * Entirely disable the YAML compile cache if `Encoding.default_internal` is set to an encoding not supported by `msgpack`. (#398)
110
+ `Psych` coerce strings to `Encoding.default_internal`, but `MessagePack` doesn't. So in this scenario we can't provide
111
+ YAML caching at all without returning the strings in the wrong encoding.
112
+ This never came up in practice but might as well be safe.
113
+
114
+ # 1.10.2
115
+
116
+ * Reduce the `Kernel.require` extra stack frames some more. Now bootsnap should only add one extra frame per `require` call.
117
+
118
+ * Better check `freeze` option support in JSON compile cache.
119
+ Previously `JSON.load_file(..., freeze: true)` would be cached even when the msgpack version is missing support for it.
120
+
121
+ # 1.10.1
122
+
123
+ * Fix `Kernel#autoload`'s fallback path always being executed.
124
+
125
+ * Consider `unlink` failing with `ENOENT` as a success.
126
+
127
+ # 1.10.0
128
+
129
+ * Delay requiring `FileUtils`. (#285)
130
+ `FileUtils` can be installed as a gem, so it's best to wait for bundler to have setup the load path before requiring it.
131
+
132
+ * Improve support of Psych 4. (#392)
133
+ Since `1.8.0`, `YAML.load_file` was no longer cached when Psych 4 was used. This is because `load_file` loads
134
+ in safe mode by default, so the Bootsnap cache could defeat that safety.
135
+ Now when precompiling YAML files, Bootsnap first try to parse them in safe mode, and if it can't fallback to unsafe mode,
136
+ and the cache contains a flag that records whether it was generated in safe mode or not.
137
+ `YAML.unsafe_load_file` will use safe caches just fine, but `YAML.load_file` will fallback to uncached YAML parsing
138
+ if the cache was generated using unsafe parsing.
139
+
140
+ * Minimize the Kernel.require extra stack frames. (#393)
141
+ This should reduce the noise generated by bootsnap on `LoadError`.
142
+
143
+ # 1.9.4
144
+
145
+ * Ignore absolute paths in the loaded feature index. (#385)
146
+ This fixes a compatibility issue with Zeitwerk when Zeitwerk is loaded before bootsnap. It also should
147
+ reduce the memory usage and improve load performance of Zeitwerk managed files.
148
+
149
+ * Automatically invalidate the load path cache whenever the Ruby version change. (#387)
150
+ This is to avoid issues in case the same installation path is re-used for subsequent ruby patch releases.
151
+
152
+ # 1.9.3
153
+
154
+ * Only disable the compile cache for source files impacted by [Ruby 3.0.3 [Bug 18250]](https://bugs.ruby-lang.org/issues/18250).
155
+ This should keep the performance loss to a minimum.
156
+
157
+ # 1.9.2
158
+
159
+ * Disable compile cache if [Ruby 3.0.3's ISeq cache bug](https://bugs.ruby-lang.org/issues/18250) is detected.
160
+ AKA `iseq.rb:13 to_binary: wrong argument type false (expected Symbol)`
161
+ * Fix `Kernel.load` behavior: before `load 'a'` would load `a.rb` (and other tried extensions) and wouldn't load `a` unless `development_mode: true`, now only `a` would be loaded and files with extensions wouldn't be.
162
+
163
+ # 1.9.1
164
+
165
+ * Removed a forgotten debug statement in JSON precompilation.
166
+
167
+ # 1.9.0
168
+
169
+ * Added a compilation cache for `JSON.load_file`. (#370)
170
+
171
+ # 1.8.1
172
+
173
+ * Fixed support for older Psych. (#369)
174
+
175
+ # 1.8.0
176
+
177
+ * Improve support for Psych 4. (#368)
178
+
179
+ # 1.7.7
180
+
181
+ * Fix `require_relative` in evaled code on latest ruby 3.1.0-dev. (#366)
182
+
183
+ # 1.7.6
184
+
185
+ * Fix reliance on `set` to be required.
186
+ * Fix `Encoding::UndefinedConversionError` error for Rails applications when precompiling cache. (#364)
187
+
188
+ # 1.7.5
189
+
190
+ * Handle a regression of Ruby 2.7.3 causing Bootsnap to call the deprecated `untaint` method. (#360)
191
+ * Gracefully handle read-only file system as well as other errors preventing to persist the load path cache. (#358)
192
+
193
+ # 1.7.4
194
+
195
+ * Stop raising errors when encountering various file system errors. The cache is now best effort,
196
+ if somehow it can't be saved, bootsnap will gracefully fallback to the original operation (e.g. `Kernel.require`).
197
+ (#353, #177, #262)
198
+
199
+ # 1.7.3
200
+
201
+ * Disable YAML precompilation when encountering YAML tags. (#351)
202
+
203
+ # 1.7.2
204
+
205
+ * Fix compatibility with msgpack < 1. (#349)
206
+
207
+ # 1.7.1
208
+
209
+ * Warn Ruby 2.5 users if they turn ISeq caching on. (#327, #244)
210
+ * Disable ISeq caching for the whole 2.5.x series again.
211
+ * Better handle hashing of Ruby strings. (#318)
212
+
213
+ # 1.7.0
214
+
215
+ * Fix detection of YAML files in gems.
216
+ * Adds an instrumentation API to monitor cache misses.
217
+ * Allow to control the behavior of `require 'bootsnap/setup'` using environment variables.
218
+ * Deprecate the `disable_trace` option.
219
+ * Deprecate the `ActiveSupport::Dependencies` (AKA Classic autoloader) integration. (#344)
220
+
3
221
  # 1.6.0
4
222
 
5
223
  * Fix a Ruby 2.7/3.0 issue with `YAML.load_file` keyword arguments. (#342)
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2017 Shopify, Inc.
3
+ Copyright (c) 2017-present Shopify, Inc.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Bootsnap [![Actions Status](https://github.com/Shopify/bootsnap/workflows/ci/badge.svg)](https://github.com/Shopify/bootsnap/actions)
2
2
 
3
- Bootsnap is a library that plugs into Ruby, with optional support for `ActiveSupport` and `YAML`,
3
+ Bootsnap is a library that plugs into Ruby, with optional support for `YAML` and `JSON`,
4
4
  to optimize and cache expensive computations. See [How Does This Work](#how-does-this-work).
5
5
 
6
6
  #### Performance
@@ -11,7 +11,7 @@ to optimize and cache expensive computations. See [How Does This Work](#how-does
11
11
  - The core Shopify platform -- a rather large monolithic application -- boots about 75% faster,
12
12
  dropping from around 25s to 6.5s.
13
13
  * In Shopify core (a large app), about 25% of this gain can be attributed to `compile_cache_*`
14
- features; 75% to path caching, and ~1% to `disable_trace`. This is fairly representative.
14
+ features; 75% to path caching. This is fairly representative.
15
15
 
16
16
  ## Usage
17
17
 
@@ -29,7 +29,7 @@ If you are using Rails, add this to `config/boot.rb` immediately after `require
29
29
  require 'bootsnap/setup'
30
30
  ```
31
31
 
32
- Note that bootsnap writes to `tmp/cache` (or the path specified by `ENV['BOOTSNAP_CACHE_DIR']`),
32
+ Note that bootsnap writes to `tmp/cache` (or the path specified by `ENV['BOOTSNAP_CACHE_DIR']`),
33
33
  and that directory *must* be writable. Rails will fail to
34
34
  boot if it is not. If this is unacceptable (e.g. you are running in a read-only container and
35
35
  unwilling to mount in a writable tmpdir), you should remove this line or wrap it in a conditional.
@@ -41,7 +41,7 @@ getting progressively slower, this is almost certainly the cause.**
41
41
  It's technically possible to simply specify `gem 'bootsnap', require: 'bootsnap/setup'`, but it's
42
42
  important to load Bootsnap as early as possible to get maximum performance improvement.
43
43
 
44
- You can see how this require works [here](https://github.com/Shopify/bootsnap/blob/master/lib/bootsnap/setup.rb).
44
+ You can see how this require works [here](https://github.com/Shopify/bootsnap/blob/main/lib/bootsnap/setup.rb).
45
45
 
46
46
  If you are not using Rails, or if you are but want more control over things, add this to your
47
47
  application setup immediately after `require 'bundler/setup'` (i.e. as early as possible: the sooner
@@ -52,17 +52,16 @@ require 'bootsnap'
52
52
  env = ENV['RAILS_ENV'] || "development"
53
53
  Bootsnap.setup(
54
54
  cache_dir: 'tmp/cache', # Path to your cache
55
+ ignore_directories: ['node_modules'], # Directory names to skip.
55
56
  development_mode: env == 'development', # Current working environment, e.g. RACK_ENV, RAILS_ENV, etc
56
57
  load_path_cache: true, # Optimize the LOAD_PATH with a cache
57
- autoload_paths_cache: true, # Optimize ActiveSupport autoloads with cache
58
- disable_trace: true, # Set `RubyVM::InstructionSequence.compile_option = { trace_instruction: false }`
59
58
  compile_cache_iseq: true, # Compile Ruby code into ISeq cache, breaks coverage reporting.
60
- compile_cache_yaml: true # Compile YAML into a cache
59
+ compile_cache_yaml: true, # Compile YAML into a cache
60
+ compile_cache_json: true, # Compile JSON into a cache
61
+ readonly: true, # Use the caches but don't update them on miss or stale entries.
61
62
  )
62
63
  ```
63
64
 
64
- **Note that `disable_trace` will break debuggers and tracing.**
65
-
66
65
  **Protip:** You can replace `require 'bootsnap'` with `BootLib::Require.from_gem('bootsnap',
67
66
  'bootsnap')` using [this trick](https://github.com/Shopify/bootsnap/wiki/Bootlib::Require). This
68
67
  will help optimize boot time further if you have an extremely large `$LOAD_PATH`.
@@ -70,7 +69,22 @@ will help optimize boot time further if you have an extremely large `$LOAD_PATH`
70
69
  Note: Bootsnap and [Spring](https://github.com/rails/spring) are orthogonal tools. While Bootsnap
71
70
  speeds up the loading of individual source files, Spring keeps a copy of a pre-booted Rails process
72
71
  on hand to completely skip parts of the boot process the next time it's needed. The two tools work
73
- well together, and are both included in a newly-generated Rails applications by default.
72
+ well together.
73
+
74
+ ### Environment variables
75
+
76
+ `require 'bootsnap/setup'` behavior can be changed using environment variables:
77
+
78
+ - `BOOTSNAP_CACHE_DIR` allows to define the cache location.
79
+ - `DISABLE_BOOTSNAP` allows to entirely disable bootsnap.
80
+ - `DISABLE_BOOTSNAP_LOAD_PATH_CACHE` allows to disable load path caching.
81
+ - `DISABLE_BOOTSNAP_COMPILE_CACHE` allows to disable ISeq and YAML caches.
82
+ - `BOOTSNAP_READONLY` configure bootsnap to not update the cache on miss or stale entries.
83
+ - `BOOTSNAP_LOG` configure bootsnap to log all caches misses to STDERR.
84
+ - `BOOTSNAP_STATS` log hit rate statistics on exit. Can't be used if `BOOTSNAP_LOG` is enabled.
85
+ - `BOOTSNAP_IGNORE_DIRECTORIES` a comma separated list of directories that shouldn't be scanned.
86
+ Useful when you have large directories of non-ruby files inside `$LOAD_PATH`.
87
+ It defaults to ignore any directory named `node_modules`.
74
88
 
75
89
  ### Environments
76
90
 
@@ -78,6 +92,23 @@ All Bootsnap features are enabled in development, test, production, and all othe
78
92
 
79
93
  If you would like to disable any feature for a certain environment, we suggest changing the configuration to take into account the appropriate ENV var or configuration according to your needs.
80
94
 
95
+ ### Instrumentation
96
+
97
+ Bootsnap cache misses can be monitored though a callback:
98
+
99
+ ```ruby
100
+ Bootsnap.instrumentation = ->(event, path) { puts "#{event} #{path}" }
101
+ ```
102
+
103
+ `event` is either `:hit`, `:miss`, `:stale` or `:revalidated`.
104
+ You can also call `Bootsnap.log!` as a shortcut to log all events to STDERR.
105
+
106
+ To turn instrumentation back off you can set it to nil:
107
+
108
+ ```ruby
109
+ Bootsnap.instrumentation = nil
110
+ ```
111
+
81
112
  ## How does this work?
82
113
 
83
114
  Bootsnap optimizes methods to cache results of expensive computations, and can be grouped
@@ -85,13 +116,12 @@ into two broad categories:
85
116
 
86
117
  * [Path Pre-Scanning](#path-pre-scanning)
87
118
  * `Kernel#require` and `Kernel#load` are modified to eliminate `$LOAD_PATH` scans.
88
- * `ActiveSupport::Dependencies.{autoloadable_module?,load_missing_constant,depend_on}` are
89
- overridden to eliminate scans of `ActiveSupport::Dependencies.autoload_paths`.
90
119
  * [Compilation caching](#compilation-caching)
91
120
  * `RubyVM::InstructionSequence.load_iseq` is implemented to cache the result of ruby bytecode
92
121
  compilation.
93
122
  * `YAML.load_file` is modified to cache the result of loading a YAML object in MessagePack format
94
123
  (or Marshal, if the message uses types unsupported by MessagePack).
124
+ * `JSON.load_file` is modified to cache the result of loading a JSON object in MessagePack format
95
125
 
96
126
  ### Path Pre-Scanning
97
127
 
@@ -125,10 +155,6 @@ open y/foo.rb
125
155
  ...
126
156
  ```
127
157
 
128
- Exactly the same strategy is employed for methods that traverse
129
- `ActiveSupport::Dependencies.autoload_paths` if the `autoload_paths_cache` option is given to
130
- `Bootsnap.setup`.
131
-
132
158
  The following diagram flowcharts the overrides that make the `*_path_cache` features work.
133
159
 
134
160
  ![Flowchart explaining
@@ -144,7 +170,7 @@ The only directories considered "stable" are things under the Ruby install prefi
144
170
  "volatile".
145
171
 
146
172
  In addition to the [`Bootsnap::LoadPathCache::Cache`
147
- source](https://github.com/Shopify/bootsnap/blob/master/lib/bootsnap/load_path_cache/cache.rb),
173
+ source](https://github.com/Shopify/bootsnap/blob/main/lib/bootsnap/load_path_cache/cache.rb),
148
174
  this diagram may help clarify how entry resolution works:
149
175
 
150
176
  ![How path searching works](https://cloud.githubusercontent.com/assets/3074765/25388270/670b5652-299b-11e7-87fb-975647f68981.png)
@@ -166,9 +192,9 @@ translated ruby source to an internal bytecode format, which is then executed by
166
192
  allows caching that bytecode. This allows us to bypass the relatively-expensive compilation step on
167
193
  subsequent loads of the same file.
168
194
 
169
- We also noticed that we spend a lot of time loading YAML documents during our application boot, and
170
- that MessagePack and Marshal are *much* faster at deserialization than YAML, even with a fast
171
- implementation. We use the same strategy of compilation caching for YAML documents, with the
195
+ We also noticed that we spend a lot of time loading YAML and JSON documents during our application boot, and
196
+ that MessagePack and Marshal are *much* faster at deserialization than YAML and JSON, even with a fast
197
+ implementation. We use the same strategy of compilation caching for YAML and JSON documents, with the
172
198
  equivalent of Ruby's "bytecode" format being a MessagePack document (or, in the case of YAML
173
199
  documents with types unsupported by MessagePack, a Marshal stream).
174
200
 
@@ -215,9 +241,9 @@ Bootsnap writes a cache file containing a 64 byte header followed by the cache c
215
241
  is a cache key including several fields:
216
242
 
217
243
  * `version`, hardcoded in bootsnap. Essentially a schema version;
218
- * `ruby_platform`, A hash of `RUBY_PLATFORM` (e.g. x86_64-linux-gnu) variable and glibc version (on Linux) or OS version (`uname -v` on BSD, macOS)
244
+ * `ruby_platform`, A hash of `RUBY_PLATFORM` (e.g. x86_64-linux-gnu) variable.
219
245
  * `compile_option`, which changes with `RubyVM::InstructionSequence.compile_option` does;
220
- * `ruby_revision`, the version of Ruby this was compiled with;
246
+ * `ruby_revision`, A hash of `RUBY_REVISION`, the exact version of Ruby;
221
247
  * `size`, the size of the source file;
222
248
  * `mtime`, the last-modification timestamp of the source file when it was compiled; and
223
249
  * `data_size`, the number of bytes following the header, which we need to read it into a buffer.
data/exe/bootsnap CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'bootsnap/cli'
4
+ require "bootsnap/cli"
5
5
  exit Bootsnap::CLI.new(ARGV).run