bootsnap 0.2.9 → 0.3.0

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
  SHA1:
3
- metadata.gz: fe31f9a445fa33edd58c5f58e0f661c0e08d2004
4
- data.tar.gz: e01345ff505baf0ce9aa6a104325a93092d0ab53
3
+ metadata.gz: 3725f53309883dce83894e47eedbb4d8322eabd5
4
+ data.tar.gz: 81e14b1d48fc4431f6ac9bb2729cfb4a69aa0f5c
5
5
  SHA512:
6
- metadata.gz: c319a87aa7d1db72c3535e0af539cd8629852238b4b88bcc1b4a7cf57ea978707aa82b879730815e293c5944b4c40d8b2531a8639780491853c58b66de01191e
7
- data.tar.gz: d2d6042b09014425a6d4feb3d1abe28c1a1eaeddd1c29fff8752ba907322349129d065c38109b6d460438b667a72b04626165a59cde12f7af509c9043ba254e5
6
+ metadata.gz: 5a2b45cb55ceffdb5751561b3a35c476ea29bcd3d3a2a68a46521240d35cc1e61cf9ac90265db751b09967655969c7a685725878b5f80a61fd38a0efd7024458
7
+ data.tar.gz: 7f7975023cb1856d5ccada63e8be2e3ab94a751d4b80121821f2b01df6cbb94f5172041020ebb9300b63760da3fc2776e3b9b56160b95b4b0c07f82fbce07860
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ os: osx
2
+ language: ruby
3
+ rvm: ruby-2.4.0
4
+ before_script: rake
5
+ script: bin/testunit
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # 0.3.0
2
+
3
+ * Migrate CompileCache from xattr as a cache backend to a cache directory
4
+ * Adds support for Linux and FreeBSD
5
+
6
+ # 0.2.15
7
+
8
+ * Support more versions of ActiveSupport (`depend_on`'s signature varies; don't reiterate it)
9
+ * Fix bug in handling autoloaded modules that raise NoMethodError
data/README.md CHANGED
@@ -1,10 +1,15 @@
1
- # Bootsnap
1
+ # Bootsnap ![CI status](https://travis-ci.org/Shopify/bootsnap.svg?branch=master)
2
2
 
3
3
  **Beta-quality. See [the last section of this README](#trustworthiness).**
4
4
 
5
5
  Bootsnap is a library that plugs into a number of Ruby and (optionally) `ActiveSupport` and `YAML`
6
6
  methods to optimize and cache expensive computations. See [the How Does This Work section](#how-does-this-work) for more information.
7
7
 
8
+ #### Quick Performance Overview
9
+ - [Discourse](https://github.com/discourse/discourse) reports a boot time reduction of approximately 50%, from roughly 6 to 3 seconds on one machine;
10
+ - One of our smaller internal apps also sees a reduction of 50%, from 3.6 to 1.8 seconds;
11
+ - The core Shopify platform -- a rather large monolithic application -- boots about 75% faster, dropping from around 25s to 6.5s.
12
+
8
13
  ## Usage
9
14
 
10
15
  Add `bootsnap` to your `Gemfile`:
@@ -112,7 +117,8 @@ result too, raising a `LoadError` without touching the filesystem at all.
112
117
 
113
118
  ### Compilation Caching
114
119
 
115
- *(A simpler implementation of this concept can be found in [yomikomu](https://github.com/ko1/yomikomu)).*
120
+ *(A more readable implementation of this concept can be found in
121
+ [yomikomu](https://github.com/ko1/yomikomu)).*
116
122
 
117
123
  Ruby has complex grammar and parsing it is not a particularly cheap operation. Since 1.9, Ruby has
118
124
  translated ruby source to an internal bytecode format, which is then executed by the Ruby VM. Since
@@ -126,9 +132,8 @@ implementation. We use the same strategy of compilation caching for YAML documen
126
132
  equivalent of Ruby's "bytecode" format being a MessagePack document (or, in the case of YAML
127
133
  documents with types unsupported by MessagePack, a Marshal stream).
128
134
 
129
- These compilation results are stored using `xattr`s on the source files. This is likely to change in
130
- the future, as it has some limitations (notably precluding Linux support except where the user feels
131
- like changing mount flags). However, this is a very performant implementation.
135
+ These compilation results are stored in a cache directory, with filenames generated by taking a hash
136
+ of the full expanded path of the input file (FNV1a-64).
132
137
 
133
138
  Whereas before, the sequence of syscalls generated to `require` a file would look like:
134
139
 
@@ -150,32 +155,36 @@ With bootsnap, we get:
150
155
  ```
151
156
  open /c/foo.rb -> n
152
157
  fstat64 n
153
- fgetxattr n
154
- fgetxattr n
158
+ close n
159
+ open /c/foo.rb -> n
160
+ fstat64 n
161
+ open (cache) -> m
162
+ read m
163
+ read m
164
+ close m
155
165
  close n
156
166
  ```
157
167
 
158
- Bootsnap writes two `xattrs` attached to each file read:
168
+ This may look worse at a glance, but underlies a large performance difference.
159
169
 
160
- * `user.aotcc.value`, the binary compilation result; and
161
- * `user.aotcc.key`, a cache key to determine whether `user.aotcc.value` is still valid.
170
+ *(The first three syscalls in both listings -- `open`, `fstat64`, `close` -- are not inherently
171
+ useful. [This ruby patch](https://bugs.ruby-lang.org/issues/13378) optimizes them out when coupled
172
+ with bootsnap.)*
162
173
 
163
- The key includes several fields:
174
+ Bootsnap writes a cache file containing a 64 byte header followed by the cache contents. The header
175
+ is a cache key including several fields:
164
176
 
165
177
  * `version`, hardcoded in bootsnap. Essentially a schema version;
178
+ * `os_version`, A hash of the current kernel version (on macOS, BSD) or glibc version (on Linux);
166
179
  * `compile_option`, which changes with `RubyVM::InstructionSequence.compile_option` does;
167
- * `data_size`, the number of bytes in `user.aotcc.value`, which we need to read it into a buffer
168
- using `fgetxattr(2)`;
169
- * `ruby_revision`, the version of Ruby this was compiled with; and
170
- * `mtime`, the last-modification timestamp of the source file when it was compiled.
180
+ * `ruby_revision`, the version of Ruby this was compiled with;
181
+ * `size`, the size of the source file;
182
+ * `mtime`, the last-modification timestamp of the source file when it was compiled; and
183
+ * `data_size`, the number of bytes following the header, which we need to read it into a buffer.
171
184
 
172
185
  If the key is valid, the result is loaded from the value. Otherwise, it is regenerated and clobbers
173
186
  the current cache.
174
187
 
175
- This diagram may help illustrate how it works:
176
-
177
- ![Compilation Caching](https://burkelibbey.s3.amazonaws.com/bootsnap-compile-cache.png)
178
-
179
188
  ### Putting it all together
180
189
 
181
190
  Imagine we have this file structure:
@@ -219,8 +228,13 @@ With bootsnap, we get:
219
228
  ```
220
229
  open /c/foo.rb -> n
221
230
  fstat64 n
222
- fgetxattr n
223
- fgetxattr n
231
+ close n
232
+ open /c/foo.rb -> n
233
+ fstat64 n
234
+ open (cache) -> m
235
+ read m
236
+ read m
237
+ close m
224
238
  close n
225
239
  ```
226
240
 
@@ -245,8 +259,8 @@ open /c/nope.bundle -> -1
245
259
 
246
260
  We use the `*_path_cache` features in production and haven't experienced any issues in a long time.
247
261
 
248
- The `compile_cache_*` features work well for us in development on macOS, but probably don't work on
249
- Linux at all.
262
+ The `compile_cache_*` features work well for us in development on macOS. It should work on Linux,
263
+ and we intend to deploy it in production, but haven't we haven't yet.
250
264
 
251
265
  `disable_trace` should be completely safe, but we don't really use it because some people like to
252
266
  use tools that make use of `trace` instructions.
@@ -256,5 +270,5 @@ use tools that make use of `trace` instructions.
256
270
  | `load_path_cache` | everywhere |
257
271
  | `autoload_path_cache` | everywhere |
258
272
  | `disable_trace` | nowhere, but it's safe unless you need tracing |
259
- | `compile_cache_iseq` | development, unlikely to work on Linux |
260
- | `compile_cache_yaml` | development, unlikely to work on Linux |
273
+ | `compile_cache_iseq` | development, but probably safe to use everywhere |
274
+ | `compile_cache_yaml` | development, but probably safe to use everywhere |
data/bootsnap.gemspec CHANGED
@@ -23,12 +23,14 @@ Gem::Specification.new do |spec|
23
23
  spec.require_paths = ["lib"]
24
24
  spec.extensions = ['ext/bootsnap/extconf.rb']
25
25
 
26
+ spec.required_ruby_version = '>= 2.3.0'
27
+
26
28
  spec.add_development_dependency "bundler", '~> 1'
27
29
  spec.add_development_dependency 'rake', '~> 10.0'
28
30
  spec.add_development_dependency 'rake-compiler', '~> 0'
29
31
  spec.add_development_dependency "minitest", "~> 5.0"
30
32
  spec.add_development_dependency "mocha", "~> 1.2"
33
+ spec.add_development_dependency "ffi-xattr", "~> 0.1.2"
31
34
 
32
35
  spec.add_runtime_dependency "msgpack", "~> 1.0"
33
- spec.add_runtime_dependency "snappy", "~> 0.0.15"
34
36
  end
data/dev.yml CHANGED
@@ -1,3 +1,6 @@
1
+ env:
2
+ BOOTSNAP_PEDANTIC: '1'
3
+
1
4
  up:
2
5
  - ruby: 2.3.3
3
6
  - bundler