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 +4 -4
- data/.travis.yml +5 -0
- data/CHANGELOG.md +9 -0
- data/README.md +39 -25
- data/bootsnap.gemspec +3 -1
- data/dev.yml +3 -0
- data/ext/bootsnap/bootsnap.c +546 -394
- data/ext/bootsnap/bootsnap.h +1 -3
- data/ext/bootsnap/extconf.rb +15 -4
- data/lib/bootsnap/compile_cache/iseq.rb +7 -1
- data/lib/bootsnap/compile_cache/yaml.rb +2 -1
- data/lib/bootsnap/compile_cache.rb +3 -3
- data/lib/bootsnap/load_path_cache/cache.rb +10 -10
- data/lib/bootsnap/load_path_cache/core_ext/active_support.rb +7 -2
- data/lib/bootsnap/load_path_cache/path.rb +7 -0
- data/lib/bootsnap/load_path_cache/store.rb +4 -4
- data/lib/bootsnap/version.rb +1 -1
- data/lib/bootsnap.rb +1 -0
- metadata +12 -10
data/ext/bootsnap/bootsnap.h
CHANGED
data/ext/bootsnap/extconf.rb
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
require "mkmf"
|
|
2
|
-
$CFLAGS << ' -O3
|
|
3
|
-
$CFLAGS << ' -
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
$CFLAGS << ' -O3 '
|
|
3
|
+
$CFLAGS << ' -std=c99'
|
|
4
|
+
|
|
5
|
+
# ruby.h has some -Wpedantic fails in some cases
|
|
6
|
+
# (e.g. https://github.com/Shopify/bootsnap/issues/15)
|
|
7
|
+
unless ['0', '', nil].include?(ENV['BOOTSNAP_PEDANTIC'])
|
|
8
|
+
$CFLAGS << ' -Wall'
|
|
9
|
+
$CFLAGS << ' -Werror'
|
|
10
|
+
$CFLAGS << ' -Wextra'
|
|
11
|
+
$CFLAGS << ' -Wpedantic'
|
|
12
|
+
|
|
13
|
+
$CFLAGS << ' -Wno-unused-parameter' # VALUE self has to be there but we don't care what it is.
|
|
14
|
+
$CFLAGS << ' -Wno-keyword-macro' # hiding return
|
|
15
|
+
end
|
|
16
|
+
|
|
6
17
|
create_makefile("bootsnap/bootsnap")
|
|
@@ -4,6 +4,10 @@ require 'zlib'
|
|
|
4
4
|
module Bootsnap
|
|
5
5
|
module CompileCache
|
|
6
6
|
module ISeq
|
|
7
|
+
class << self
|
|
8
|
+
attr_accessor :cache_dir
|
|
9
|
+
end
|
|
10
|
+
|
|
7
11
|
def self.input_to_storage(_, path)
|
|
8
12
|
RubyVM::InstructionSequence.compile_file(path).to_binary
|
|
9
13
|
rescue SyntaxError
|
|
@@ -28,6 +32,7 @@ module Bootsnap
|
|
|
28
32
|
module InstructionSequenceMixin
|
|
29
33
|
def load_iseq(path)
|
|
30
34
|
Bootsnap::CompileCache::Native.fetch(
|
|
35
|
+
Bootsnap::CompileCache::ISeq.cache_dir,
|
|
31
36
|
path.to_s,
|
|
32
37
|
Bootsnap::CompileCache::ISeq
|
|
33
38
|
)
|
|
@@ -62,7 +67,8 @@ module Bootsnap
|
|
|
62
67
|
Bootsnap::CompileCache::Native.compile_option_crc32 = crc
|
|
63
68
|
end
|
|
64
69
|
|
|
65
|
-
def self.install!
|
|
70
|
+
def self.install!(cache_dir)
|
|
71
|
+
Bootsnap::CompileCache::ISeq.cache_dir = cache_dir
|
|
66
72
|
Bootsnap::CompileCache::ISeq.compile_option_updated
|
|
67
73
|
class << RubyVM::InstructionSequence
|
|
68
74
|
prepend InstructionSequenceMixin
|
|
@@ -30,7 +30,7 @@ module Bootsnap
|
|
|
30
30
|
::YAML.load(data)
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
def self.install!
|
|
33
|
+
def self.install!(cache_dir)
|
|
34
34
|
require 'yaml'
|
|
35
35
|
require 'msgpack'
|
|
36
36
|
|
|
@@ -44,6 +44,7 @@ module Bootsnap
|
|
|
44
44
|
klass = class << ::YAML; self; end
|
|
45
45
|
klass.send(:define_method, :load_file) do |path|
|
|
46
46
|
Bootsnap::CompileCache::Native.fetch(
|
|
47
|
+
cache_dir,
|
|
47
48
|
path.to_s,
|
|
48
49
|
Bootsnap::CompileCache::YAML
|
|
49
50
|
)
|
|
@@ -3,13 +3,13 @@ require_relative 'compile_cache/yaml'
|
|
|
3
3
|
|
|
4
4
|
module Bootsnap
|
|
5
5
|
module CompileCache
|
|
6
|
-
def self.setup(iseq:, yaml:)
|
|
6
|
+
def self.setup(cache_dir:, iseq:, yaml:)
|
|
7
7
|
if iseq
|
|
8
|
-
Bootsnap::CompileCache::ISeq.install!
|
|
8
|
+
Bootsnap::CompileCache::ISeq.install!(cache_dir)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
if yaml
|
|
12
|
-
Bootsnap::CompileCache::YAML.install!
|
|
12
|
+
Bootsnap::CompileCache::YAML.install!(cache_dir)
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
end
|
|
@@ -54,22 +54,20 @@ module Bootsnap
|
|
|
54
54
|
x = search_index(feature)
|
|
55
55
|
return x if x
|
|
56
56
|
|
|
57
|
+
# Ruby has some built-in features that require lies about.
|
|
58
|
+
# For example, 'enumerator' is built in. If you require it, ruby
|
|
59
|
+
# returns false as if it were already loaded; however, there is no
|
|
60
|
+
# file to find on disk. We've pre-built a list of these, and we
|
|
61
|
+
# return false if any of them is loaded.
|
|
62
|
+
raise LoadPathCache::ReturnFalse if BUILTIN_FEATURES.key?(feature)
|
|
63
|
+
|
|
57
64
|
# The feature wasn't found on our preliminary search through the index.
|
|
58
65
|
# We resolve this differently depending on what the extension was.
|
|
59
66
|
case File.extname(feature)
|
|
60
67
|
# If the extension was one of the ones we explicitly cache (.rb and the
|
|
61
68
|
# native dynamic extension, e.g. .bundle or .so), we know it was a
|
|
62
69
|
# failure and there's nothing more we can do to find the file.
|
|
63
|
-
when *CACHED_EXTENSIONS # .rb, .bundle or .so
|
|
64
|
-
nil
|
|
65
|
-
# If no extension was specified, it's the same situation, since we
|
|
66
|
-
# try appending both cachable extensions in search_index. However,
|
|
67
|
-
# there's a special-case for 'enumerator'. Before ruby 1.9, you had
|
|
68
|
-
# to `require 'enumerator'` to use it. In 1.9+, it's pre-loaded, but
|
|
69
|
-
# doesn't correspond to any entry on the filesystem. Ruby lies. So we
|
|
70
|
-
# lie too, forcing our monkeypatch to return false like ruby would.
|
|
71
|
-
when ""
|
|
72
|
-
raise LoadPathCache::ReturnFalse if BUILTIN_FEATURES.key?(feature)
|
|
70
|
+
when '', *CACHED_EXTENSIONS # no extension, .rb, (.bundle or .so)
|
|
73
71
|
nil
|
|
74
72
|
# Ruby allows specifying native extensions as '.so' even when DLEXT
|
|
75
73
|
# is '.bundle'. This is where we handle that case.
|
|
@@ -122,6 +120,7 @@ module Bootsnap
|
|
|
122
120
|
@store.transaction do
|
|
123
121
|
paths.map(&:to_s).each do |path|
|
|
124
122
|
p = Path.new(path)
|
|
123
|
+
next if p.non_directory?
|
|
125
124
|
entries, dirs = p.entries_and_dirs(@store)
|
|
126
125
|
# push -> low precedence -> set only if unset
|
|
127
126
|
dirs.each { |dir| @dirs[dir] ||= true }
|
|
@@ -134,6 +133,7 @@ module Bootsnap
|
|
|
134
133
|
@store.transaction do
|
|
135
134
|
paths.map(&:to_s).reverse.each do |path|
|
|
136
135
|
p = Path.new(path)
|
|
136
|
+
next if p.non_directory?
|
|
137
137
|
entries, dirs = p.entries_and_dirs(@store)
|
|
138
138
|
# unshift -> high precedence -> unconditional set
|
|
139
139
|
dirs.each { |dir| @dirs[dir] = true }
|
|
@@ -4,7 +4,10 @@ module Bootsnap
|
|
|
4
4
|
module ActiveSupport
|
|
5
5
|
def self.with_bootsnap_fallback(error)
|
|
6
6
|
yield
|
|
7
|
-
rescue error
|
|
7
|
+
rescue error => e
|
|
8
|
+
# NoMethodError is a NameError, but we only want to handle actual
|
|
9
|
+
# NameError instances.
|
|
10
|
+
raise unless e.class == error
|
|
8
11
|
without_bootsnap_cache { yield }
|
|
9
12
|
end
|
|
10
13
|
|
|
@@ -50,7 +53,9 @@ module Bootsnap
|
|
|
50
53
|
CoreExt::ActiveSupport.with_bootsnap_fallback(NameError) { super }
|
|
51
54
|
end
|
|
52
55
|
|
|
53
|
-
|
|
56
|
+
# Signature has changed a few times over the years; easiest to not
|
|
57
|
+
# reiterate it with version polymorphism here...
|
|
58
|
+
def depend_on(*)
|
|
54
59
|
CoreExt::ActiveSupport.with_bootsnap_fallback(LoadError) { super }
|
|
55
60
|
end
|
|
56
61
|
end
|
|
@@ -23,6 +23,13 @@ module Bootsnap
|
|
|
23
23
|
@path = path.to_s
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
# True if the path exists, but represents a non-directory object
|
|
27
|
+
def non_directory?
|
|
28
|
+
!File.stat(path).directory?
|
|
29
|
+
rescue Errno::ENOENT
|
|
30
|
+
false
|
|
31
|
+
end
|
|
32
|
+
|
|
26
33
|
# Return a list of all the requirable files and all of the subdirectories
|
|
27
34
|
# of this +Path+.
|
|
28
35
|
def entries_and_dirs(store)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
require_relative '../explicit_require'
|
|
2
2
|
|
|
3
|
-
Bootsnap::ExplicitRequire.with_gems('snappy') { require 'snappy' }
|
|
4
3
|
Bootsnap::ExplicitRequire.with_gems('msgpack') { require 'msgpack' }
|
|
5
4
|
Bootsnap::ExplicitRequire.from_rubylibdir('fileutils')
|
|
6
5
|
|
|
@@ -58,8 +57,9 @@ module Bootsnap
|
|
|
58
57
|
|
|
59
58
|
def load_data
|
|
60
59
|
@data = begin
|
|
61
|
-
MessagePack.load(
|
|
62
|
-
|
|
60
|
+
MessagePack.load(File.binread(@store_path))
|
|
61
|
+
# handle malformed data due to upgrade incompatability
|
|
62
|
+
rescue Errno::ENOENT, MessagePack::MalformedFormatError, MessagePack::UnknownExtTypeError
|
|
63
63
|
{}
|
|
64
64
|
end
|
|
65
65
|
end
|
|
@@ -69,7 +69,7 @@ module Bootsnap
|
|
|
69
69
|
# caches if they read at an inopportune time.
|
|
70
70
|
tmp = "#{@store_path}.#{(rand * 100000).to_i}.tmp"
|
|
71
71
|
FileUtils.mkpath(File.dirname(tmp))
|
|
72
|
-
File.binwrite(tmp,
|
|
72
|
+
File.binwrite(tmp, MessagePack.dump(@data))
|
|
73
73
|
FileUtils.mv(tmp, @store_path)
|
|
74
74
|
end
|
|
75
75
|
end
|
data/lib/bootsnap/version.rb
CHANGED
data/lib/bootsnap.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: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Burke Libbey
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2017-
|
|
11
|
+
date: 2017-05-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -81,33 +81,33 @@ dependencies:
|
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
82
|
version: '1.2'
|
|
83
83
|
- !ruby/object:Gem::Dependency
|
|
84
|
-
name:
|
|
84
|
+
name: ffi-xattr
|
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
|
86
86
|
requirements:
|
|
87
87
|
- - "~>"
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
|
-
version:
|
|
90
|
-
type: :
|
|
89
|
+
version: 0.1.2
|
|
90
|
+
type: :development
|
|
91
91
|
prerelease: false
|
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements:
|
|
94
94
|
- - "~>"
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
|
-
version:
|
|
96
|
+
version: 0.1.2
|
|
97
97
|
- !ruby/object:Gem::Dependency
|
|
98
|
-
name:
|
|
98
|
+
name: msgpack
|
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
|
100
100
|
requirements:
|
|
101
101
|
- - "~>"
|
|
102
102
|
- !ruby/object:Gem::Version
|
|
103
|
-
version:
|
|
103
|
+
version: '1.0'
|
|
104
104
|
type: :runtime
|
|
105
105
|
prerelease: false
|
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
|
107
107
|
requirements:
|
|
108
108
|
- - "~>"
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
|
-
version:
|
|
110
|
+
version: '1.0'
|
|
111
111
|
description: wip.
|
|
112
112
|
email:
|
|
113
113
|
- burke.libbey@shopify.com
|
|
@@ -118,6 +118,8 @@ extra_rdoc_files: []
|
|
|
118
118
|
files:
|
|
119
119
|
- ".gitignore"
|
|
120
120
|
- ".rubocop.yml"
|
|
121
|
+
- ".travis.yml"
|
|
122
|
+
- CHANGELOG.md
|
|
121
123
|
- CONTRIBUTING.md
|
|
122
124
|
- Gemfile
|
|
123
125
|
- LICENSE
|
|
@@ -157,7 +159,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
157
159
|
requirements:
|
|
158
160
|
- - ">="
|
|
159
161
|
- !ruby/object:Gem::Version
|
|
160
|
-
version:
|
|
162
|
+
version: 2.3.0
|
|
161
163
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
162
164
|
requirements:
|
|
163
165
|
- - ">="
|