bootsnap 1.1.0.pre → 1.1.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: eb4f1c7a20afd5550cb29063940865fa1b7cf1a6
4
- data.tar.gz: 1309c503d7c4fedbd07a30efc8fbe1cdb7fd44c7
3
+ metadata.gz: fbdf0cc19b09b396571d9d38cb037cebfcdab7b2
4
+ data.tar.gz: f07f07ec071dbffe3a48e1ae324457729a11ca61
5
5
  SHA512:
6
- metadata.gz: 712729db38aedc0316e4d2043dc3eb3f72cd6560915052ee3bf9fc19de74a5c6534716d2607ac312bb074f8df529f76a9fdfd584d746356280dc96c43fb8de3c
7
- data.tar.gz: a978d40c13d3b665910571224d378d75ec7d6c1779e8fc535bf88efc3c290e948d681f055a2ae1fcd0d6ae84df0e8ef501714c4e12c2e420357de4e7995f9dae
6
+ metadata.gz: 9db4ab87163f7c05a7b5c62fe17617149ec5acdc1caf186013c334222a4ad0a2087c5992b44fcf424201dd5b12448ce25826ccb4f99f495e450437aa90d0a0ae
7
+ data.tar.gz: 84714b27f6a3be1650807af151309dc789390944c1a317ec9c246067c2f4299184c182aa878c8eb5715da989c1c768a3d86992af02ab9d974f1d26d09bb2d170
@@ -2,6 +2,8 @@
2
2
 
3
3
  * Add `bootsnap/setup`
4
4
  * Support jruby (without compile caching features)
5
+ * Better deoptimization when Coverage is enabled
6
+ * Consider `Bundler.bundle_path` to be stable
5
7
 
6
8
  # 1.0.0
7
9
 
data/README.md CHANGED
@@ -1,11 +1,11 @@
1
- # Bootsnap ![CI status](https://travis-ci.org/Shopify/bootsnap.svg?branch=master)
1
+ # Bootsnap [![Build Status](https://travis-ci.org/Shopify/bootsnap.svg?branch=master)](https://travis-ci.org/Shopify/bootsnap)
2
2
 
3
3
  **Beta-quality. See [the last section of this README](#trustworthiness).**
4
4
 
5
- Bootsnap is a library that plugs into a number of Ruby and (optionally) `ActiveSupport` and `YAML`
6
- methods to optimize and cache expensive computations. See [the How Does This Work section](#how-does-this-work) for more information.
5
+ Bootsnap is a library that plugs into Ruby, with optional support for `ActiveSupport` and `YAML`,
6
+ to optimize and cache expensive computations. See [How Does This Work](#how-does-this-work).
7
7
 
8
- #### Quick Performance Overview
8
+ #### Performance
9
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
10
  - One of our smaller internal apps also sees a reduction of 50%, from 3.6 to 1.8 seconds;
11
11
  - The core Shopify platform -- a rather large monolithic application -- boots about 75% faster, dropping from around 25s to 6.5s.
@@ -32,14 +32,15 @@ this is loaded, the sooner it can start optimizing things)
32
32
 
33
33
  ```ruby
34
34
  require 'bootsnap'
35
+ env = ENV['RAILS_ENV'] || "development"
35
36
  Bootsnap.setup(
36
- cache_dir: 'tmp/cache', # Path to your cache
37
- development_mode: ENV['RAILS_ENV'] == 'development', # This should be set to whatever evaluates your current working environment, e.g. RACK_ENV, RAILS_ENV, etc
38
- load_path_cache: true, # Should we optimize the LOAD_PATH with a cache?
39
- autoload_paths_cache: true, # Should we optimize ActiveSupport autoloads with cache?
40
- disable_trace: false, # Sets `RubyVM::InstructionSequence.compile_option = { trace_instruction: false }`
41
- compile_cache_iseq: true, # Should compile Ruby code into ISeq cache?
42
- compile_cache_yaml: true # Should compile YAML into a cache?
37
+ cache_dir: 'tmp/cache', # Path to your cache
38
+ development_mode: env == 'development', # Current working environment, e.g. RACK_ENV, RAILS_ENV, etc
39
+ load_path_cache: true, # Optimize the LOAD_PATH with a cache
40
+ autoload_paths_cache: true, # Optimize ActiveSupport autoloads with cache
41
+ disable_trace: true, # (Alpha) Set `RubyVM::InstructionSequence.compile_option = { trace_instruction: false }`
42
+ compile_cache_iseq: true, # Compile Ruby code into ISeq cache, breaks coverage reporting.
43
+ compile_cache_yaml: true # Compile YAML into a cache
43
44
  )
44
45
  ```
45
46
 
@@ -49,8 +50,7 @@ will help optimize boot time further if you have an extremely large `$LOAD_PATH`
49
50
 
50
51
  ## How does this work?
51
52
 
52
- Bootsnap is a library that plugs into a number of Ruby and (optionally) `ActiveSupport` and `YAML`
53
- methods. These methods are modified to cache results of expensive computations, and can be grouped
53
+ Bootsnap optimizes methods to cache results of expensive computations, and can be grouped
54
54
  into two broad categories:
55
55
 
56
56
  * [Path Pre-Scanning](#path-pre-scanning)
@@ -110,7 +110,8 @@ entries do not expire -- once their contents has been scanned, it is assumed to
110
110
 
111
111
  The only directories considered "stable" are things under the Ruby install prefix
112
112
  (`RbConfig::CONFIG['prefix']`, e.g. `/usr/local/ruby` or `~/.rubies/x.y.z`), and things under the
113
- `Gem.path` (e.g. `~/.gem/ruby/x.y.z`). Everything else is considered "volatile".
113
+ `Gem.path` (e.g. `~/.gem/ruby/x.y.z`) or `Bundler.bundle_path`. Everything else is considered
114
+ "volatile".
114
115
 
115
116
  In addition to the [`Bootsnap::LoadPathCache::Cache`
116
117
  source](https://github.com/Shopify/bootsnap/blob/master/lib/bootsnap/load_path_cache/cache.rb),
@@ -34,7 +34,6 @@ Gem::Specification.new do |spec|
34
34
  spec.add_development_dependency 'rake-compiler', '~> 0'
35
35
  spec.add_development_dependency "minitest", "~> 5.0"
36
36
  spec.add_development_dependency "mocha", "~> 1.2"
37
- spec.add_development_dependency "ffi-xattr", "~> 0.1.2"
38
37
 
39
38
  spec.add_runtime_dependency "msgpack", "~> 1.0"
40
39
  end
@@ -18,7 +18,9 @@
18
18
  #include <errno.h>
19
19
  #include <fcntl.h>
20
20
  #include <sys/stat.h>
21
+ #ifndef _WIN32
21
22
  #include <sys/utsname.h>
23
+ #endif
22
24
 
23
25
  /* 1000 is an arbitrary limit; FNV64 plus some slashes brings the cap down to
24
26
  * 981 for the cache dir */
@@ -109,6 +111,15 @@ struct s2o_data;
109
111
  struct i2o_data;
110
112
  struct i2s_data;
111
113
 
114
+ /* https://bugs.ruby-lang.org/issues/13667 */
115
+ extern VALUE rb_get_coverages(void);
116
+ static VALUE
117
+ bs_rb_coverage_running(VALUE self)
118
+ {
119
+ VALUE cov = rb_get_coverages();
120
+ return RTEST(cov) ? Qtrue : Qfalse;
121
+ }
122
+
112
123
  /*
113
124
  * Ruby C extensions are initialized by calling Init_<extname>.
114
125
  *
@@ -129,6 +140,7 @@ Init_bootsnap(void)
129
140
 
130
141
  uncompilable = rb_intern("__bootsnap_uncompilable__");
131
142
 
143
+ rb_define_module_function(rb_mBootsnap_CompileCache_Native, "coverage_running?", bs_rb_coverage_running, 0);
132
144
  rb_define_module_function(rb_mBootsnap_CompileCache_Native, "fetch", bs_rb_fetch, 3);
133
145
  rb_define_module_function(rb_mBootsnap_CompileCache_Native, "compile_option_crc32=", bs_compile_option_crc32_set, 1);
134
146
  }
@@ -176,6 +188,9 @@ fnv1a_64(const char *str)
176
188
  static uint32_t
177
189
  get_os_version(void)
178
190
  {
191
+ #ifdef _WIN32
192
+ return (uint32_t)GetVersion();
193
+ #else
179
194
  uint64_t hash;
180
195
  struct utsname utsname;
181
196
 
@@ -185,6 +200,7 @@ get_os_version(void)
185
200
  hash = fnv1a_64(utsname.version);
186
201
 
187
202
  return (uint32_t)(hash >> 32);
203
+ #endif
188
204
  }
189
205
 
190
206
  /*
@@ -265,6 +281,9 @@ open_current_file(char * path, struct bs_cache_key * key)
265
281
 
266
282
  fd = open(path, O_RDONLY);
267
283
  if (fd < 0) return fd;
284
+ #ifdef _WIN32
285
+ setmode(fd, O_BINARY);
286
+ #endif
268
287
 
269
288
  if (fstat(fd, &statbuf) < 0) {
270
289
  close(fd);
@@ -321,6 +340,9 @@ open_cache_file(const char * path, struct bs_cache_key * key)
321
340
  if (errno == ENOENT) return CACHE_MISSING_OR_INVALID;
322
341
  return ERROR_WITH_ERRNO;
323
342
  }
343
+ #ifdef _WIN32
344
+ setmode(fd, O_BINARY);
345
+ #endif
324
346
 
325
347
  res = bs_read_key(fd, key);
326
348
  if (res < 0) {
@@ -393,7 +415,11 @@ mkpath(char * file_path, mode_t mode)
393
415
  char * p;
394
416
  for (p = strchr(file_path + 1, '/'); p; p = strchr(p + 1, '/')) {
395
417
  *p = '\0';
418
+ #ifdef _WIN32
419
+ if (mkdir(file_path) == -1) {
420
+ #else
396
421
  if (mkdir(file_path, mode) == -1) {
422
+ #endif
397
423
  if (errno != EEXIST) {
398
424
  *p = '/';
399
425
  return -1;
@@ -428,6 +454,9 @@ atomic_write_cache_file(char * path, struct bs_cache_key * key, VALUE data)
428
454
  fd = open(tmp_path, O_WRONLY | O_CREAT, 0644);
429
455
  if (fd < 0) return -1;
430
456
  }
457
+ #ifdef _WIN32
458
+ setmode(fd, O_BINARY);
459
+ #endif
431
460
 
432
461
  key->data_size = RSTRING_LEN(data);
433
462
  nwrite = write(fd, key, KEY_SIZE);
@@ -12,12 +12,6 @@ module Bootsnap
12
12
  RubyVM::InstructionSequence.compile_file(path).to_binary
13
13
  rescue SyntaxError
14
14
  raise Uncompilable, 'syntax error'
15
- rescue RuntimeError => e
16
- if e.message == 'should not compile with coverage'
17
- raise Uncompilable, 'coverage is enabled'
18
- else
19
- raise
20
- end
21
15
  end
22
16
 
23
17
  def self.storage_to_output(binary)
@@ -37,6 +31,9 @@ module Bootsnap
37
31
 
38
32
  module InstructionSequenceMixin
39
33
  def load_iseq(path)
34
+ # Having coverage enabled prevents iseq dumping/loading.
35
+ return nil if defined?(Coverage) && Bootsnap::CompileCache::Native.coverage_running?
36
+
40
37
  Bootsnap::CompileCache::Native.fetch(
41
38
  Bootsnap::CompileCache::ISeq.cache_dir,
42
39
  path.to_s,
@@ -47,18 +44,6 @@ module Bootsnap
47
44
  puts "unmatched platform for file #{path}"
48
45
  end
49
46
  raise
50
- rescue Errno::ERANGE
51
- STDERR.puts <<~EOF
52
- \x1b[31mError loading ISeq from cache for \x1b[1;34m#{path}\x1b[0;31m!
53
- You can likely fix this by running:
54
- \x1b[1;32mxattr -c #{path}
55
- \x1b[0;31m...but, first, please make sure \x1b[1;34m@burke\x1b[0;31m knows you ran into this bug!
56
- He will want to see the results of:
57
- \x1b[1;32m/bin/ls -l@ #{path}
58
- \x1b[0;31mand:
59
- \x1b[1;32mxattr -p user.aotcc.key #{path}\x1b[0m
60
- EOF
61
- raise
62
47
  end
63
48
 
64
49
  def compile_option=(hash)
@@ -48,7 +48,7 @@ module Bootsnap
48
48
  def find(feature)
49
49
  reinitialize if (@has_relative_paths && dir_changed?) || stale?
50
50
  feature = feature.to_s
51
- return feature if feature.start_with?(SLASH)
51
+ return feature if absolute_path?(feature)
52
52
  return File.expand_path(feature) if feature.start_with?('./')
53
53
  @mutex.synchronize do
54
54
  x = search_index(feature)
@@ -85,6 +85,16 @@ module Bootsnap
85
85
  end
86
86
  end
87
87
 
88
+ if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
89
+ def absolute_path?(path)
90
+ path[1] == ':'
91
+ end
92
+ else
93
+ def absolute_path?(path)
94
+ path.start_with?(SLASH)
95
+ end
96
+ end
97
+
88
98
  def unshift_paths(sender, *paths)
89
99
  return unless sender == @path_obj
90
100
  @mutex.synchronize { unshift_paths_locked(*paths) }
@@ -99,6 +99,8 @@ module Bootsnap
99
99
  @stability ||= begin
100
100
  if Gem.path.detect { |p| expanded_path.start_with?(p.to_s) }
101
101
  STABLE
102
+ elsif expanded_path.start_with?(Bundler.bundle_path.to_s)
103
+ STABLE
102
104
  elsif expanded_path.start_with?(RUBY_LIBDIR) && !expanded_path.start_with?(RUBY_SITEDIR)
103
105
  STABLE
104
106
  else
@@ -1,3 +1,3 @@
1
1
  module Bootsnap
2
- VERSION = "1.1.0.pre"
2
+ VERSION = "1.1.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootsnap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0.pre
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Burke Libbey
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-12 00:00:00.000000000 Z
11
+ date: 2017-06-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,20 +80,6 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '1.2'
83
- - !ruby/object:Gem::Dependency
84
- name: ffi-xattr
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: 0.1.2
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: 0.1.2
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: msgpack
99
85
  requirement: !ruby/object:Gem::Requirement
@@ -163,9 +149,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
163
149
  version: 2.0.0
164
150
  required_rubygems_version: !ruby/object:Gem::Requirement
165
151
  requirements:
166
- - - ">"
152
+ - - ">="
167
153
  - !ruby/object:Gem::Version
168
- version: 1.3.1
154
+ version: '0'
169
155
  requirements: []
170
156
  rubyforge_project:
171
157
  rubygems_version: 2.6.10