iseq_rails_tools 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0b5e048c97ff3fdbd635135e589ac488d70bc0c4
4
+ data.tar.gz: 2a614cd2aa085f5a9638f2157b683dcf522a2c21
5
+ SHA512:
6
+ metadata.gz: 6cdf29659c15bdde45f5ccb455cf15fedfa17440929a6befc68d16849a3c89e43a1ec70849b0d150aaa1c000b8ab3ae251ce98d8ac17fcdadb4b42930f6e4509
7
+ data.tar.gz: 3707519c3391f1553d918295451ce636dcaa2a43be8c9305fb9eefcea211a0cff9ce964841f91c63bd1c1d47d6b5c818090afbdf964f171568aefbd7293dfd1c
@@ -0,0 +1,20 @@
1
+ Copyright 2017 Kevin Deisz
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,36 @@
1
+ # IseqRailsTools
2
+
3
+ [![Build Status](https://travis-ci.org/kddeisz/iseq-rails-tools.svg?branch=master)](https://travis-ci.org/kddeisz/iseq-rails-tools)
4
+
5
+ Since Ruby 2.3, we've had the ability to dump out compiled Ruby bytecode to files to alleviate that process when ruby files are required. This can significantly boost boot times, especially when running with larger Ruby projects.
6
+
7
+ This gem hooks into ActiveSupport's autoloading in development mode to bring AOT compiling to Rails. This can improve both the console and server boot times.
8
+
9
+ When deploying to production, you can take advantage of the quicker boot times by adding the `iseq:all` rake task to your deploy script.
10
+
11
+ ## Usage
12
+
13
+ 1. Add `iseq_rails_tools` to your `Gemfile`.
14
+ 2. Run `bundle install` to download the gem.
15
+ 3. Add `.iseq/` to your `.gitignore`.
16
+
17
+ Then when running the console or the server, the compiled files will start to be generated in a new `.iseq` directory in the root of the repository.
18
+
19
+ ## Tasks
20
+
21
+ `IseqRailsTools` adds a couple `Rake` tasks to your Rails project:
22
+
23
+ 1. `iseq:all` - Compile iseq files for all files under autoloaded paths
24
+ 2. `iseq:clear` - Clear out all compiled iseq files
25
+
26
+ ## Contributing
27
+
28
+ Bug reports and pull requests are welcome on GitHub at https://github.com/kddeisz/iseq-rails-tools.
29
+
30
+ ## License
31
+
32
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
33
+
34
+ ## Credit
35
+
36
+ A lot of the inspiration (as well as some of the code) for this gem came from Koichi Sasada's great work on the [yomikomu](https://github.com/ko1/yomikomu) gem.
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'IseqRailsTools'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+
21
+
22
+ require 'bundler/gem_tasks'
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
@@ -0,0 +1,40 @@
1
+ require 'digest/sha1'
2
+ require 'fileutils'
3
+
4
+ require 'iseq_rails_tools/compiler'
5
+ require 'iseq_rails_tools/railtie'
6
+
7
+ module IseqRailsTools
8
+ class NullCompiler
9
+ def clear_compiled_iseq_files
10
+ end
11
+
12
+ def watching?(filepath)
13
+ false
14
+ end
15
+ end
16
+
17
+ class << self
18
+ attr_accessor :compiler
19
+
20
+ def clear_compiled_iseq_files
21
+ compiler.clear_compiled_iseq_files
22
+ end
23
+
24
+ def compile_all
25
+ compiler.compile_all
26
+ end
27
+ end
28
+
29
+ self.compiler = NullCompiler.new
30
+ end
31
+
32
+ RubyVM::InstructionSequence.singleton_class.prepend(Module.new do
33
+ def load_iseq(filepath)
34
+ if ::IseqRailsTools.compiler.watching?(filepath)
35
+ ::IseqRailsTools.compiler.load_iseq(filepath)
36
+ elsif method(:load_iseq).super_method
37
+ super
38
+ end
39
+ end
40
+ end)
@@ -0,0 +1,87 @@
1
+ module IseqRailsTools
2
+ class Compiler
3
+ DIRECTORY_NAME = '.iseq'
4
+
5
+ attr_reader :application, :directory
6
+
7
+ def initialize(application)
8
+ @application = application
9
+ @directory = application.root.join(DIRECTORY_NAME).to_s
10
+ FileUtils.mkdir_p(directory) unless File.directory?(directory)
11
+ end
12
+
13
+ def clear_compiled_iseq_files
14
+ Dir.glob(File.join(directory, '**/*.yarb')) { |path| FileUtils.rm(path) }
15
+ end
16
+
17
+ def compile_all
18
+ globs.each do |glob|
19
+ Dir.glob(glob).each do |filepath|
20
+ iseq_key = iseq_key_name(filepath)
21
+ compile_and_store_iseq(filepath, iseq_key)
22
+ end
23
+ end
24
+ end
25
+
26
+ def iseq_key_name(filepath)
27
+ path = filepath.gsub("#{application.root.to_s}/", '')
28
+ .gsub(/[^A-Za-z0-9\._-]/) { |c| '%02x' % c.ord }
29
+ File.join(directory, "#{path}.yarb")
30
+ end
31
+
32
+ def load_iseq(filepath)
33
+ iseq_key = iseq_key_name(filepath)
34
+
35
+ if compiled_iseq_exist?(iseq_key) && compiled_iseq_is_younger?(filepath, iseq_key)
36
+ binary = File.binread(iseq_key)
37
+ RubyVM::InstructionSequence.load_from_binary(binary)
38
+ else
39
+ compile_and_store_iseq(filepath, iseq_key)
40
+ end
41
+ end
42
+
43
+ def recompile_modified
44
+ globs.each do |glob|
45
+ Dir.glob(glob).each do |filepath|
46
+ iseq_key = iseq_key_name(filepath)
47
+
48
+ if !compiled_iseq_exist?(iseq_key) || !compiled_iseq_is_younger?(filepath, iseq_key)
49
+ compile_and_store_iseq(filepath, iseq_key)
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ def watching?(filepath)
56
+ globs.any? { |glob| Dir.glob(glob).include?(filepath) }
57
+ end
58
+
59
+ private
60
+
61
+ def compile_and_store_iseq(filepath, iseq_key)
62
+ Rails.logger.debug("[IseqRailsTools] Compiling #{filepath}")
63
+ iseq = RubyVM::InstructionSequence.compile_file(filepath)
64
+ binary = iseq.to_binary("SHA-1:#{::Digest::SHA1.file(filepath).digest}")
65
+ File.binwrite(iseq_key, binary)
66
+ iseq
67
+ rescue SyntaxError, RuntimeError => e
68
+ puts "#{e}: #{filepath}"
69
+ nil
70
+ end
71
+
72
+ def compiled_iseq_exist?(iseq_key)
73
+ File.exist?(iseq_key)
74
+ end
75
+
76
+ def compiled_iseq_is_younger?(filepath, iseq_key)
77
+ File.mtime(iseq_key) >= File.mtime(filepath)
78
+ end
79
+
80
+ def globs
81
+ @globs ||=
82
+ application.config.iseq_compile_paths.map do |directory|
83
+ File.join(directory, '**/*.rb')
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,35 @@
1
+ module IseqRailsTools
2
+ class Railtie < ::Rails::Railtie
3
+ config.iseq_compile_paths = []
4
+
5
+ initializer 'iseq_rails_tools.initialize' do |app|
6
+ IseqRailsTools.compiler = Compiler.new(app)
7
+
8
+ # Yeah, sorry about this. This was the easiest way to get all access to
9
+ # all of the reloadable paths.
10
+ app.config.iseq_compile_paths = app.send(:_all_autoload_paths)
11
+
12
+ files =
13
+ app.config.iseq_compile_paths.flat_map do |path|
14
+ Dir.glob(File.join(path, '**/*.rb'))
15
+ end
16
+
17
+ directories =
18
+ app.config.iseq_compile_paths.map { |path| [path, 'rb'] }.to_h
19
+
20
+ reloader =
21
+ app.config.file_watcher.new(files, directories) do
22
+ Rails.logger.debug('[IseqRailsTools] Compiling files')
23
+ IseqRailsTools.compiler.recompile_modified
24
+ end
25
+
26
+ app.reloaders.unshift(reloader)
27
+ reloader.execute
28
+ end
29
+
30
+ rake_tasks do
31
+ rake_paths = File.expand_path(File.join('..', 'tasks', '*.rake'), __dir__)
32
+ Dir[rake_paths].each { |filepath| load filepath }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,3 @@
1
+ module IseqRailsTools
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,11 @@
1
+ namespace :iseq do
2
+ desc 'Compile iseq files for all files under autoloaded paths'
3
+ task all: :environment do
4
+ IseqRailsTools.compile_all
5
+ end
6
+
7
+ desc 'Clear out all compiled iseq files'
8
+ task clear: :environment do
9
+ IseqRailsTools.clear_compiled_iseq_files
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: iseq_rails_tools
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Kevin Deisz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-04-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 5.0.0
27
+ description: |2
28
+ Allows you to take advantage of ruby's AOT bytecode generation
29
+ within a Rails project.
30
+ email:
31
+ - kevin.deisz@gmail.com
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - MIT-LICENSE
37
+ - README.md
38
+ - Rakefile
39
+ - lib/iseq_rails_tools.rb
40
+ - lib/iseq_rails_tools/compiler.rb
41
+ - lib/iseq_rails_tools/railtie.rb
42
+ - lib/iseq_rails_tools/version.rb
43
+ - lib/tasks/iseq_rails_tools_tasks.rake
44
+ homepage: https://github.com/kddeisz/iseq-rails-tools
45
+ licenses:
46
+ - MIT
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 2.3.0
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubyforge_project:
64
+ rubygems_version: 2.6.11
65
+ signing_key:
66
+ specification_version: 4
67
+ summary: Use AOT compilation within Rails
68
+ test_files: []