bootsnap 1.1.0.pre-java → 1.1.1-java
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 +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +15 -14
- data/bootsnap.gemspec +0 -1
- data/ext/bootsnap/bootsnap.c +36 -2
- data/lib/bootsnap/compile_cache/iseq.rb +3 -18
- data/lib/bootsnap/load_path_cache/cache.rb +11 -1
- data/lib/bootsnap/load_path_cache/path.rb +2 -0
- data/lib/bootsnap/version.rb +1 -1
- metadata +4 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 622dbeab469dbcd40ec9e8c93d73e6ff01aa2d6c
|
4
|
+
data.tar.gz: 1f50bce28e945662a13ad63592352d64d77273be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 117a042e1ccbaef389ff7e9ed121ae3c0125544400dc3678cabe7dabb1568e4650d89b17738cc2a8dfa909ed20ee5186a59fec3df83d99753a6f89343018e910
|
7
|
+
data.tar.gz: b4aac5d35a0c8eba3a238d82ec076707917373d7dfa0c0b232cef22e0d499e72a584bb937886e260fe8817ce9e003f74bf6d91b641b2cc2bdd08febf6192b235
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,13 @@
|
|
1
|
+
# 1.1.1
|
2
|
+
|
3
|
+
* Fix crash in `Native.compile_option_crc32=` on 32-bit platforms.
|
4
|
+
|
1
5
|
# 1.1.0
|
2
6
|
|
3
7
|
* Add `bootsnap/setup`
|
4
8
|
* Support jruby (without compile caching features)
|
9
|
+
* Better deoptimization when Coverage is enabled
|
10
|
+
* Consider `Bundler.bundle_path` to be stable
|
5
11
|
|
6
12
|
# 1.0.0
|
7
13
|
|
data/README.md
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
# Bootsnap ](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
|
6
|
-
|
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
|
-
####
|
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',
|
37
|
-
development_mode:
|
38
|
-
load_path_cache: true,
|
39
|
-
autoload_paths_cache: true,
|
40
|
-
disable_trace:
|
41
|
-
compile_cache_iseq: true,
|
42
|
-
compile_cache_yaml: true
|
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
|
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
|
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),
|
data/bootsnap.gemspec
CHANGED
@@ -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
|
data/ext/bootsnap/bootsnap.c
CHANGED
@@ -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
|
}
|
@@ -136,12 +148,17 @@ Init_bootsnap(void)
|
|
136
148
|
/*
|
137
149
|
* Bootsnap's ruby code registers a hook that notifies us via this function
|
138
150
|
* when compile_option changes. These changes invalidate all existing caches.
|
151
|
+
*
|
152
|
+
* Note that on 32-bit platforms, a CRC32 can't be represented in a Fixnum, but
|
153
|
+
* can be represented by a uint.
|
139
154
|
*/
|
140
155
|
static VALUE
|
141
156
|
bs_compile_option_crc32_set(VALUE self, VALUE crc32_v)
|
142
157
|
{
|
143
|
-
|
144
|
-
|
158
|
+
if (!RB_TYPE_P(crc32_v, T_BIGNUM) && !RB_TYPE_P(crc32_v, T_FIXNUM)) {
|
159
|
+
Check_Type(crc32_v, T_FIXNUM);
|
160
|
+
}
|
161
|
+
current_compile_option_crc32 = NUM2UINT(crc32_v);
|
145
162
|
return Qnil;
|
146
163
|
}
|
147
164
|
|
@@ -176,6 +193,9 @@ fnv1a_64(const char *str)
|
|
176
193
|
static uint32_t
|
177
194
|
get_os_version(void)
|
178
195
|
{
|
196
|
+
#ifdef _WIN32
|
197
|
+
return (uint32_t)GetVersion();
|
198
|
+
#else
|
179
199
|
uint64_t hash;
|
180
200
|
struct utsname utsname;
|
181
201
|
|
@@ -185,6 +205,7 @@ get_os_version(void)
|
|
185
205
|
hash = fnv1a_64(utsname.version);
|
186
206
|
|
187
207
|
return (uint32_t)(hash >> 32);
|
208
|
+
#endif
|
188
209
|
}
|
189
210
|
|
190
211
|
/*
|
@@ -265,6 +286,9 @@ open_current_file(char * path, struct bs_cache_key * key)
|
|
265
286
|
|
266
287
|
fd = open(path, O_RDONLY);
|
267
288
|
if (fd < 0) return fd;
|
289
|
+
#ifdef _WIN32
|
290
|
+
setmode(fd, O_BINARY);
|
291
|
+
#endif
|
268
292
|
|
269
293
|
if (fstat(fd, &statbuf) < 0) {
|
270
294
|
close(fd);
|
@@ -321,6 +345,9 @@ open_cache_file(const char * path, struct bs_cache_key * key)
|
|
321
345
|
if (errno == ENOENT) return CACHE_MISSING_OR_INVALID;
|
322
346
|
return ERROR_WITH_ERRNO;
|
323
347
|
}
|
348
|
+
#ifdef _WIN32
|
349
|
+
setmode(fd, O_BINARY);
|
350
|
+
#endif
|
324
351
|
|
325
352
|
res = bs_read_key(fd, key);
|
326
353
|
if (res < 0) {
|
@@ -393,7 +420,11 @@ mkpath(char * file_path, mode_t mode)
|
|
393
420
|
char * p;
|
394
421
|
for (p = strchr(file_path + 1, '/'); p; p = strchr(p + 1, '/')) {
|
395
422
|
*p = '\0';
|
423
|
+
#ifdef _WIN32
|
424
|
+
if (mkdir(file_path) == -1) {
|
425
|
+
#else
|
396
426
|
if (mkdir(file_path, mode) == -1) {
|
427
|
+
#endif
|
397
428
|
if (errno != EEXIST) {
|
398
429
|
*p = '/';
|
399
430
|
return -1;
|
@@ -428,6 +459,9 @@ atomic_write_cache_file(char * path, struct bs_cache_key * key, VALUE data)
|
|
428
459
|
fd = open(tmp_path, O_WRONLY | O_CREAT, 0644);
|
429
460
|
if (fd < 0) return -1;
|
430
461
|
}
|
462
|
+
#ifdef _WIN32
|
463
|
+
setmode(fd, O_BINARY);
|
464
|
+
#endif
|
431
465
|
|
432
466
|
key->data_size = RSTRING_LEN(data);
|
433
467
|
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
|
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
|
data/lib/bootsnap/version.rb
CHANGED
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.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Burke Libbey
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-06-
|
11
|
+
date: 2017-06-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,20 +80,6 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '1.2'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
requirement: !ruby/object:Gem::Requirement
|
85
|
-
requirements:
|
86
|
-
- - "~>"
|
87
|
-
- !ruby/object:Gem::Version
|
88
|
-
version: 0.1.2
|
89
|
-
name: ffi-xattr
|
90
|
-
prerelease: false
|
91
|
-
type: :development
|
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
|
requirement: !ruby/object:Gem::Requirement
|
99
85
|
requirements:
|
@@ -162,9 +148,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
162
148
|
version: 2.0.0
|
163
149
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
150
|
requirements:
|
165
|
-
- - "
|
151
|
+
- - ">="
|
166
152
|
- !ruby/object:Gem::Version
|
167
|
-
version:
|
153
|
+
version: '0'
|
168
154
|
requirements: []
|
169
155
|
rubyforge_project:
|
170
156
|
rubygems_version: 2.4.8
|