tmp8-snailgun 1.2.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.
- data/README-snowleopard +15 -0
- data/README.markdown +217 -0
- data/bin/fautotest +9 -0
- data/bin/fconsole +13 -0
- data/bin/fcucumber +6 -0
- data/bin/frake +22 -0
- data/bin/fruby +28 -0
- data/bin/snailgun +150 -0
- data/bin/snailgun_ruby +45 -0
- data/lib/snailgun/client.rb +21 -0
- data/lib/snailgun/require_preload.rb +11 -0
- data/lib/snailgun/require_timings.rb +48 -0
- data/lib/snailgun/server.rb +132 -0
- data/ruby-1.9.2-p0.patch +54 -0
- metadata +88 -0
data/README-snowleopard
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
If you use ruby-1.9.2-p0 on Snow Leopard snailgun won't work out of the Box!
|
2
|
+
|
3
|
+
I have included a small patch to the ruby-sources that make it work:
|
4
|
+
|
5
|
+
(this is assuming you use rvm)
|
6
|
+
|
7
|
+
cd $HOME/.rvm/src/ruby-1.9.2-p0/ext/socket
|
8
|
+
patch -p1 < wherever_snailgun_was_installed/ruby-1.9.2-p0.patch
|
9
|
+
ruby extconf.rb
|
10
|
+
make clean
|
11
|
+
make clean install
|
12
|
+
|
13
|
+
Patch was taken from http://redmine.ruby-lang.org/repositories/revision/ruby-19?rev=29242
|
14
|
+
|
15
|
+
thieso@gmail.com 20101024
|
data/README.markdown
ADDED
@@ -0,0 +1,217 @@
|
|
1
|
+
Snailgun
|
2
|
+
========
|
3
|
+
|
4
|
+
Snailgun accelerates the startup of Ruby applications which require large
|
5
|
+
numbers of libraries. It does this by preparing a Ruby process with your
|
6
|
+
chosen libraries preloaded, and then forking that process whenever a new
|
7
|
+
command-line Ruby interpreter is required.
|
8
|
+
|
9
|
+
Installation
|
10
|
+
------------
|
11
|
+
|
12
|
+
sudo gem install snailgun
|
13
|
+
|
14
|
+
Or for the latest code, `git clone git://github.com/candlerb/snailgun.git`
|
15
|
+
and put the bin directory into your PATH.
|
16
|
+
|
17
|
+
Case 1: standalone
|
18
|
+
------------------
|
19
|
+
|
20
|
+
# WITHOUT SNAILGUN
|
21
|
+
$ time ruby -rubygems -e 'require "active_support"' -e 'puts "".blank?'
|
22
|
+
true
|
23
|
+
|
24
|
+
real 0m2.123s
|
25
|
+
user 0m1.424s
|
26
|
+
sys 0m0.168s
|
27
|
+
|
28
|
+
# WITH SNAILGUN
|
29
|
+
$ snailgun -rubygems -ractive_support
|
30
|
+
Snailgun starting on /home/brian/.snailgun/14781 - 'exit' to end
|
31
|
+
$ time fruby -e 'puts "".blank?'
|
32
|
+
true
|
33
|
+
|
34
|
+
real 0m0.064s
|
35
|
+
user 0m0.020s
|
36
|
+
sys 0m0.004s
|
37
|
+
|
38
|
+
$ exit
|
39
|
+
logout
|
40
|
+
Snailgun ended
|
41
|
+
$
|
42
|
+
|
43
|
+
Case 2: Rails app
|
44
|
+
-----------------
|
45
|
+
|
46
|
+
When using Rails or Merb, snailgun will start a process preloaded for the
|
47
|
+
`test` environment only unless told otherwise.
|
48
|
+
|
49
|
+
You need to edit `config/environments/test.rb` and set
|
50
|
+
`config.cache_classes = false`. This is so that your application classes
|
51
|
+
are loaded each time you run a test, rather than being preloaded into
|
52
|
+
the test environment.
|
53
|
+
|
54
|
+
Snailgun will take several seconds to be ready to process requests. Start
|
55
|
+
with `snailgun -v` if you wish to be notified when it is ready.
|
56
|
+
|
57
|
+
$ rails testapp
|
58
|
+
$ cd testapp
|
59
|
+
$ vi config/environments/test.rb
|
60
|
+
... set config.cache_classes = false
|
61
|
+
$ snailgun
|
62
|
+
Now entering subshell. Use 'exit' to terminate snailgun
|
63
|
+
|
64
|
+
$ time RAILS_ENV=test fruby script/runner 'puts 1+2'
|
65
|
+
3
|
66
|
+
|
67
|
+
real 0m0.169s
|
68
|
+
user 0m0.040s
|
69
|
+
sys 0m0.008s
|
70
|
+
|
71
|
+
# To run your test suite
|
72
|
+
$ frake test # or frake spec
|
73
|
+
|
74
|
+
Your preloaded process will remain around until you type `exit` to terminate
|
75
|
+
it.
|
76
|
+
|
77
|
+
Note that any attempt by `fruby` or `frake` to perform an action in an
|
78
|
+
environment other than 'test' will fail. See below for how to run multiple
|
79
|
+
snailgun environments.
|
80
|
+
|
81
|
+
Merb support has been contributed (using MERB_ENV), but it is untested by
|
82
|
+
me.
|
83
|
+
|
84
|
+
Case 3: Rails with multiple environments
|
85
|
+
----------------------------------------
|
86
|
+
|
87
|
+
After reading the warnings below, you may choose to start multiple snailgun
|
88
|
+
processes each configured for a different environment, as follows:
|
89
|
+
|
90
|
+
$ snailgun --rails test,development
|
91
|
+
|
92
|
+
This gives the potential for faster startup of rake tasks which involve
|
93
|
+
the development environment (such as migrations) and the console. The
|
94
|
+
utility `fconsole` is provided for this.
|
95
|
+
|
96
|
+
However, beware that frake and fruby need to decide which of the preloaded
|
97
|
+
environments to dispatch the command to. The safest way is to force the
|
98
|
+
correct one explicitly:
|
99
|
+
|
100
|
+
RAILS_ENV=test frake test:units
|
101
|
+
RAILS_ENV=development fruby script/server
|
102
|
+
RAILS_ENV=test fruby script/runner 'puts "".blank?'
|
103
|
+
|
104
|
+
If you do not specify the environment, then a simple heuristic is used:
|
105
|
+
|
106
|
+
* `fruby` always defaults to the 'development' environment.
|
107
|
+
|
108
|
+
* `frake` honours any `RAILS_ENV=xxx` setting on the command line. If
|
109
|
+
missing, `frake` defaults to the 'test' environment if no args are given or
|
110
|
+
if an arg containing the word 'test' or 'spec' is given; otherwise it falls
|
111
|
+
back to the 'development' environment.
|
112
|
+
|
113
|
+
WARNING: The decision as to which of the preloaded environments to use is
|
114
|
+
made *before* actually running the command. If the wrong choice is made, it
|
115
|
+
can lead to problems.
|
116
|
+
|
117
|
+
In the worst case, you may have a 'test'-type task, but find that it is
|
118
|
+
wrongly dispatched to your 'development' environment - and possibly ends up
|
119
|
+
blowing away your development database. This actually happened to me while
|
120
|
+
developing snailgun. SO IF YOUR DEVELOPMENT DATABASE CONTAINS USEFUL DATA,
|
121
|
+
KEEP IT BACKED UP.
|
122
|
+
|
123
|
+
If you run test files individually, it is especially critical that you set
|
124
|
+
the correct environment. e.g.
|
125
|
+
|
126
|
+
RAILS_ENV=test fruby -Ilib -Itest test/unit/some_test.rb
|
127
|
+
|
128
|
+
Case 4: Rails with cucumber
|
129
|
+
---------------------------
|
130
|
+
|
131
|
+
Cucumber creates its own Rails environment called "cucumber", so you can
|
132
|
+
setup snailgun like this:
|
133
|
+
|
134
|
+
$ snailgun --rails test,cucumber
|
135
|
+
|
136
|
+
Then use `frake cucumber` to exercise the features. frake selects the
|
137
|
+
"cucumber" environment if run with "cucumber" as an argument.
|
138
|
+
|
139
|
+
NOTE: to make your model classes be loaded on each run you need to set
|
140
|
+
`config.cache_classes = false` in `config/environments/cucumber.rb`.
|
141
|
+
Cucumber will give a big warning saying that this is known to be a
|
142
|
+
problem with transactional fixtures. I don't use transactional fixtures
|
143
|
+
so this isn't a problem for me.
|
144
|
+
|
145
|
+
For a substantial performance boost, remove `:lib=>false` lines from
|
146
|
+
`config/environments/cucumber.rb` so that cucumber, webrat, nokogiri etc
|
147
|
+
are preloaded.
|
148
|
+
|
149
|
+
Smaller performance boosts can be had from further preloading. For example,
|
150
|
+
cucumber makes use of some rspec libraries for diffing even if you're not
|
151
|
+
using rspec, so you can preload those. Add something like this to the end of
|
152
|
+
`config/environments/cucumber.rb`
|
153
|
+
|
154
|
+
begin
|
155
|
+
require 'spec/expectations'
|
156
|
+
require 'spec/runner/differs/default'
|
157
|
+
rescue LoadError
|
158
|
+
end
|
159
|
+
require 'test_help'
|
160
|
+
require 'test/unit/testresult'
|
161
|
+
require 'active_support/secure_random'
|
162
|
+
require 'active_support/time_with_zone'
|
163
|
+
|
164
|
+
autotest
|
165
|
+
--------
|
166
|
+
|
167
|
+
There is some simple support for autotest (from the ZenTest package).
|
168
|
+
Just type `fautotest` instead of `autotest` after snailgun has been started.
|
169
|
+
This hasn't been tested for a while.
|
170
|
+
|
171
|
+
Bypassing rubygems
|
172
|
+
------------------
|
173
|
+
|
174
|
+
You can get noticeably faster startup if you don't use rubygems to invoke
|
175
|
+
the programs. To do this, you can add the binary directory directly into
|
176
|
+
the front of your PATH, e.g. for Ubuntu
|
177
|
+
|
178
|
+
PATH=/var/lib/gems/1.8/gems/snailgun-1.0.3/bin:$PATH
|
179
|
+
|
180
|
+
Alternatively, create a file called `fruby` somewhere early on in your PATH
|
181
|
+
(e.g. under `$HOME/bin`), like this:
|
182
|
+
|
183
|
+
#!/usr/bin/env ruby
|
184
|
+
load '/path/to/the/real/fruby'
|
185
|
+
|
186
|
+
Repeat for `frake` etc.
|
187
|
+
|
188
|
+
Other bugs and limitations
|
189
|
+
--------------------------
|
190
|
+
Only works with Linux/BSD systems, due to use of passing open file
|
191
|
+
descriptors across a socket.
|
192
|
+
|
193
|
+
Ctrl-C doesn't terminate frake processes.
|
194
|
+
|
195
|
+
`fruby script/console` doesn't give any speedup, because script/console uses
|
196
|
+
exec to invoke irb. Use the supplied `fconsole` instead.
|
197
|
+
|
198
|
+
The environment is not currently passed across the socket to the ruby
|
199
|
+
process. This means it's not usable as a fast CGI replacement.
|
200
|
+
|
201
|
+
In Rails, you need to beware that any changes to your `config/environment*`
|
202
|
+
will not be reflected until you stop and restart snailgun.
|
203
|
+
|
204
|
+
Licence
|
205
|
+
-------
|
206
|
+
This code is released under the same licence as Ruby itself.
|
207
|
+
|
208
|
+
Author
|
209
|
+
------
|
210
|
+
Brian Candler <B.Candler@pobox.com>
|
211
|
+
|
212
|
+
Credits:
|
213
|
+
|
214
|
+
* Jan X <jan.h.xie@gmail.com>
|
215
|
+
* George Ogata <george.ogata@gmail.com>
|
216
|
+
* Niklas Hofer <niklas+dev@lanpartei.de>
|
217
|
+
* Thies C. Arntzen <thieso@gmail.com>
|
data/bin/fautotest
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Copyright (C) Brian Candler 2009. Released under the Ruby licence.
|
3
|
+
|
4
|
+
# shortcut for: RAILS_ENV=test fruby /path/to/autotest
|
5
|
+
|
6
|
+
ENV["RAILS_ENV"] = "test"
|
7
|
+
Test::Unit.run = true if defined?(Test::Unit) && Test::Unit.respond_to?(:run=)
|
8
|
+
ARGV[0,0] = ["-e","gem 'ZenTest'","-e","load Gem.bin_path('ZenTest', 'autotest')","--"]
|
9
|
+
load File.join(File.dirname(__FILE__), "fruby")
|
data/bin/fconsole
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Copyright (C) Brian Candler 2009. Released under the Ruby licence.
|
3
|
+
|
4
|
+
ENV['RAILS_ENV'] = ARGV.shift if ARGV[0] =~ /^\w/
|
5
|
+
|
6
|
+
ARGV[0,0] = [
|
7
|
+
"-rirb",
|
8
|
+
"-rirb/completion",
|
9
|
+
"-rconsole_app",
|
10
|
+
"-rconsole_with_helpers",
|
11
|
+
"-eIRB.start", "--", "--simple-prompt"
|
12
|
+
]
|
13
|
+
load File.join(File.dirname(__FILE__), "fruby")
|
data/bin/fcucumber
ADDED
data/bin/frake
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Copyright (C) Brian Candler 2009. Released under the Ruby licence.
|
3
|
+
# Here we run rake within a pre-forked ruby process
|
4
|
+
|
5
|
+
# Pre-parse environment - see collect_tasks in rake/lib/rake.rb
|
6
|
+
ARGV.each do |arg|
|
7
|
+
if arg =~ /^(\w+)=(.*)$/
|
8
|
+
ENV[$1] = $2
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Rails/Merb: make a guess at the correct environment
|
13
|
+
if File.exist?("config/boot.rb") || File.exist?("config/init.rb")
|
14
|
+
if ARGV.find { |arg| arg =~ /\bcucumber\b/ }
|
15
|
+
$DEFAULT_ENV='cucumber'
|
16
|
+
elsif ARGV.find { |arg| arg =~ /\b(test|spec)\b/ } || !ARGV.find { |arg| arg !~ /^-/ }
|
17
|
+
$DEFAULT_ENV='test'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
ARGV[0,0] = ["-rrake", "-eRake.application.run", "--"]
|
22
|
+
load File.join(File.dirname(__FILE__), "fruby")
|
data/bin/fruby
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Copyright (C) Brian Candler 2009. Released under the Ruby licence.
|
3
|
+
# This could be rewritten in C for even faster startup
|
4
|
+
|
5
|
+
require 'lib/snailgun/client'
|
6
|
+
|
7
|
+
if ENV['SNAILGUN_SOCK']
|
8
|
+
sockname = ENV['SNAILGUN_SOCK']
|
9
|
+
elsif File.directory?('tmp/sockets/snailgun')
|
10
|
+
env = ENV['RAILS_ENV'] || ENV['MERB_ENV']
|
11
|
+
unless env
|
12
|
+
# Normally default to development: see railties/lib/tasks/misc.rake
|
13
|
+
env = $DEFAULT_ENV || 'development'
|
14
|
+
STDERR.puts "Snailgun assuming environment '#{env}'"
|
15
|
+
end
|
16
|
+
sockname = "tmp/sockets/snailgun/#{env}"
|
17
|
+
end
|
18
|
+
|
19
|
+
unless sockname and File.exists? sockname
|
20
|
+
STDERR.puts <<EOS
|
21
|
+
Unable to find path to snailgun socket.
|
22
|
+
- did you run this in a session with a snailgun parent?
|
23
|
+
- you can do 'SNAILGUN_SOCK=/path/to/sock #{$0} ...'
|
24
|
+
EOS
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
|
28
|
+
Snailgun::Client.new(sockname)
|
data/bin/snailgun
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Copyright (C) Brian Candler 2009. Released under the Ruby licence.
|
3
|
+
|
4
|
+
# Turn on copy-on-write garbage collection in REE: see
|
5
|
+
# http://www.rubyenterpriseedition.com/documentation.html#_copy_on_write_friendliness
|
6
|
+
begin
|
7
|
+
GC.copy_on_write_friendly = true
|
8
|
+
rescue NoMethodError
|
9
|
+
end
|
10
|
+
|
11
|
+
$:.unshift File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
|
12
|
+
require 'snailgun/server'
|
13
|
+
require 'optparse'
|
14
|
+
|
15
|
+
sockpath = nil
|
16
|
+
mode = nil
|
17
|
+
envs = "test"
|
18
|
+
rake = false
|
19
|
+
verbose = false
|
20
|
+
|
21
|
+
def fix_rake
|
22
|
+
require 'rbconfig'
|
23
|
+
Config::CONFIG['bindir'] = File.expand_path(File.dirname(__FILE__))
|
24
|
+
Config::CONFIG['ruby_install_name'] = 'fruby'
|
25
|
+
require 'rubygems'
|
26
|
+
require 'rake'
|
27
|
+
require 'rake/testtask'
|
28
|
+
require 'rake/rdoctask'
|
29
|
+
end
|
30
|
+
|
31
|
+
OptionParser.new do |opts|
|
32
|
+
opts.on("-I DIR", "add to load path") { |v| $:.unshift v }
|
33
|
+
opts.on("-r LIB", "require library") { |v| require v }
|
34
|
+
opts.on("--rails [ENVS]", "rails mode") { |v| mode = :rails; envs = v }
|
35
|
+
opts.on("--ruby [SOCKPATH]", "ruby mode") { |v| mode = :ruby; sockpath = v }
|
36
|
+
opts.on("--rake", "add rake support") { rake = true }
|
37
|
+
opts.on("-v", "--verbose", "show progress") { verbose = true }
|
38
|
+
end.parse!
|
39
|
+
|
40
|
+
mode ||= if File.exist?("config/boot.rb")
|
41
|
+
:rails
|
42
|
+
elsif File.exist?("config/init.rb")
|
43
|
+
:merb
|
44
|
+
else
|
45
|
+
:ruby
|
46
|
+
end
|
47
|
+
|
48
|
+
STDERR.puts "Starting in #{mode} mode" if verbose
|
49
|
+
case mode
|
50
|
+
when :ruby
|
51
|
+
unless sockpath
|
52
|
+
dir = File.join(ENV['HOME'], '.snailgun')
|
53
|
+
begin
|
54
|
+
Dir.mkdir dir, 0700
|
55
|
+
rescue Errno::EEXIST
|
56
|
+
File.chmod 0700, dir
|
57
|
+
end
|
58
|
+
sockpath = File.join dir, $$.to_s
|
59
|
+
end
|
60
|
+
fix_rake if rake
|
61
|
+
server = Snailgun::Server.new(sockpath)
|
62
|
+
server.interactive!
|
63
|
+
|
64
|
+
when :rails
|
65
|
+
conf = File.expand_path('config/boot.rb')
|
66
|
+
unless File.exist?(conf)
|
67
|
+
raise "#{conf} does not exist, cannot continue"
|
68
|
+
end
|
69
|
+
sockdir = File.expand_path('tmp/sockets/snailgun')
|
70
|
+
begin
|
71
|
+
Dir.mkdir sockdir, 0700
|
72
|
+
rescue Errno::EEXIST
|
73
|
+
File.chmod 0700, sockdir
|
74
|
+
end
|
75
|
+
pids = {}
|
76
|
+
fix_rake # TODO: separate process for rake (but then need to choose right RAILS_ENV)
|
77
|
+
|
78
|
+
start_for_envs = envs.split(/[\s,]+/).uniq
|
79
|
+
start_for_envs.each do |env|
|
80
|
+
pids[env] = fork do
|
81
|
+
STDERR.puts "Server starting for RAILS_ENV=#{env}"
|
82
|
+
server = Snailgun::Server.new("#{sockdir}/#{env}")
|
83
|
+
ENV['RAILS_ENV'] = env
|
84
|
+
load conf
|
85
|
+
|
86
|
+
if File.exist?('./.snailgun.preload')
|
87
|
+
require 'snailgun/require_preload'
|
88
|
+
else
|
89
|
+
puts "please create a .snailgun.preload by ..."
|
90
|
+
end
|
91
|
+
|
92
|
+
if Rails.respond_to?(:configuration) && Rails.configuration.cache_classes
|
93
|
+
STDERR.puts <<-EOS
|
94
|
+
WARNING: Snailgun doesn't work well with `cache_classes`. Strongly recommend
|
95
|
+
`config.cache_classes = false` in config/environments/#{env}.rb
|
96
|
+
EOS
|
97
|
+
end
|
98
|
+
STDERR.puts "Server ready for RAILS_ENV=#{env}"
|
99
|
+
server.run
|
100
|
+
end
|
101
|
+
end
|
102
|
+
if start_for_envs.size == 1
|
103
|
+
ENV['RAILS_ENV'] = start_for_envs.first
|
104
|
+
STDERR.puts "Now entering subshell for RAILS_ENV=#{ENV['RAILS_ENV']}. Use 'exit' to terminate snailgun"
|
105
|
+
else
|
106
|
+
STDERR.puts "Now entering subshell Don't forget to set your RAILS_ENV!. Use 'exit' to terminate snailgun"
|
107
|
+
end
|
108
|
+
Snailgun::Server.shell
|
109
|
+
pids.each do |env,pid|
|
110
|
+
Process.kill('TERM',pid)
|
111
|
+
end
|
112
|
+
# TODO: wait a few secs for them to die, 'KILL' if required
|
113
|
+
STDERR.puts "Snailgun ended"
|
114
|
+
|
115
|
+
when :merb
|
116
|
+
conf = File.expand_path('config/init.rb')
|
117
|
+
unless File.exist?(conf)
|
118
|
+
raise '#{conf} does not exist, cannot continue'
|
119
|
+
end
|
120
|
+
sockdir = File.expand_path('tmp/sockets/snailgun')
|
121
|
+
begin
|
122
|
+
require 'fileutils'
|
123
|
+
FileUtils.mkdir_p sockdir
|
124
|
+
ensure
|
125
|
+
File.chmod 0700, sockdir
|
126
|
+
end
|
127
|
+
pids = {}
|
128
|
+
fix_rake # TODO: separate process for rake (but then need to choose right RAILS_ENV)
|
129
|
+
envs.split(/\s*,\s*/).uniq.each do |env|
|
130
|
+
pids[env] = fork do
|
131
|
+
server = Snailgun::Server.new("#{sockdir}/#{env}")
|
132
|
+
ENV['MERB_ENV'] = env
|
133
|
+
|
134
|
+
require 'rubygems'
|
135
|
+
gem 'merb-core'
|
136
|
+
require 'merb'
|
137
|
+
Merb.start_environment([env])
|
138
|
+
|
139
|
+
STDERR.puts "Started server for #{env}" if verbose
|
140
|
+
server.run
|
141
|
+
end
|
142
|
+
end
|
143
|
+
STDERR.puts "Use 'exit' to terminate snailgun"
|
144
|
+
Snailgun::Server.shell
|
145
|
+
pids.each do |env,pid|
|
146
|
+
Process.kill('TERM',pid)
|
147
|
+
end
|
148
|
+
# TODO: wait a few secs for them to die, 'KILL' if required
|
149
|
+
STDERR.puts "Snailgun ended"
|
150
|
+
end
|
data/bin/snailgun_ruby
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
|
3
|
+
require 'snailgun/client'
|
4
|
+
|
5
|
+
def rvm_env(path)
|
6
|
+
if File.exist?(file = "#{path}/.rvmrc")
|
7
|
+
ruby, gemset = IO.read(file).strip.split(" ").last.split("@")
|
8
|
+
Dir["#{ENV['rvm_path']}/environments/*#{ruby}*@#{gemset}"].first
|
9
|
+
elsif path != "/"
|
10
|
+
rvm_env(File.expand_path("#{path}/../"))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def snailgun_socket(path)
|
15
|
+
if File.socket?(socket = "#{path}/tmp/sockets/snailgun/test")
|
16
|
+
socket
|
17
|
+
elsif path != "/"
|
18
|
+
snailgun_socket(File.expand_path("#{path}/../"))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def skip_snailgun?
|
23
|
+
ARGV.size == 1 && ARGV[0] =~ /^\/tmp\/cucumber/
|
24
|
+
end
|
25
|
+
|
26
|
+
def log(msg)
|
27
|
+
File.open("/tmp/snailgun_ruby.log", "a+") { |f| f.puts msg }
|
28
|
+
end
|
29
|
+
|
30
|
+
cwd = Dir.pwd
|
31
|
+
|
32
|
+
if !skip_snailgun? && (socket = snailgun_socket(cwd))
|
33
|
+
log "fruby #{ARGV.inspect}"
|
34
|
+
Snailgun::Client.new(socket)
|
35
|
+
else
|
36
|
+
if rvm_env = rvm_env(cwd)
|
37
|
+
require 'shellwords'
|
38
|
+
args = ARGV.map { |a| Shellwords.shellescape(a) }.join(" ")
|
39
|
+
log "exec:bash -c 'source #{rvm_env}; ruby #{args}'"
|
40
|
+
Kernel.exec('bash', "-c", "source #{rvm_env}; ruby #{args}")
|
41
|
+
else
|
42
|
+
log "exec:ruby #{ARGV.inspect}\""
|
43
|
+
Kernel.exec('ruby', *ARGV)
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'socket'
|
2
|
+
module Snailgun
|
3
|
+
class Client
|
4
|
+
def initialize(sockname)
|
5
|
+
server = UNIXSocket.open(sockname)
|
6
|
+
server.send_io(STDIN)
|
7
|
+
server.send_io(STDOUT)
|
8
|
+
server.send_io(STDERR)
|
9
|
+
args = Marshal.dump([ARGV, ENV.to_hash, Dir.pwd, Process.getpgrp])
|
10
|
+
server.write [args.size].pack("N")
|
11
|
+
server.write args
|
12
|
+
begin
|
13
|
+
rc = (server.read(1) || "\000").unpack("C").first
|
14
|
+
exit rc
|
15
|
+
rescue Interrupt
|
16
|
+
server.write('X')
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
ignore = File.exist?(".snailgun.ignore") ? IO.read(".snailgun.ignore").split : []
|
2
|
+
(IO.read(".snailgun.preload") rescue '').split.each do |path|
|
3
|
+
next if ignore.include?(path)
|
4
|
+
next if path =~ /^#/
|
5
|
+
puts "snailgun.preload: #{path}"
|
6
|
+
begin
|
7
|
+
require path
|
8
|
+
rescue Exception => e
|
9
|
+
puts "cannot preload:'#{path}' 'cause of:#{e.message}"
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
|
3
|
+
$require_level = 0
|
4
|
+
$required = []
|
5
|
+
|
6
|
+
class SnailgunPreloader
|
7
|
+
@@preload_file = "#{File.expand_path(Dir.pwd)}/.snailgun.preload"
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def load_file(path)
|
11
|
+
File.exist?(path) ? IO.read(path).split : []
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_to_preload(path)
|
15
|
+
ignore = load_file(".snailgun.ignore")
|
16
|
+
already_marked_for_preloading = load_file(@@preload_file)
|
17
|
+
unless ignore.include?(path) || already_marked_for_preloading.include?(path)
|
18
|
+
puts "adding #{path}"
|
19
|
+
File.open(@@preload_file, "a+") { |f| f.puts path }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module Kernel
|
26
|
+
alias require_without_timing require
|
27
|
+
def require(path)
|
28
|
+
result = seconds = nil
|
29
|
+
|
30
|
+
begin
|
31
|
+
$require_level += 1
|
32
|
+
seconds = Benchmark.realtime { result = require_without_timing(path) }
|
33
|
+
ensure
|
34
|
+
$require_level -= 1
|
35
|
+
end
|
36
|
+
|
37
|
+
if result == true && $require_level == 0
|
38
|
+
SnailgunPreloader.add_to_preload(path)
|
39
|
+
end
|
40
|
+
|
41
|
+
# if result
|
42
|
+
# puts "R:#{'%.5f' % seconds} #{' '*$require_level}#{path} "
|
43
|
+
# end
|
44
|
+
|
45
|
+
result
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# Copyright (C) Brian Candler 2009. Released under the Ruby licence.
|
2
|
+
|
3
|
+
# Our at_exit handler must be called *last*, so register it first
|
4
|
+
at_exit { $SNAILGUN_EXIT.call if $SNAILGUN_EXIT }
|
5
|
+
|
6
|
+
# Fix truncation of $0. See http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/336743
|
7
|
+
$progname = $0
|
8
|
+
alias $PROGRAM_NAME $0
|
9
|
+
alias $0 $progname
|
10
|
+
trace_var(:$0) {|val| $PROGRAM_NAME = val} # update for ps
|
11
|
+
|
12
|
+
require 'socket'
|
13
|
+
require 'optparse'
|
14
|
+
require 'shellwords'
|
15
|
+
|
16
|
+
module Snailgun
|
17
|
+
class Server
|
18
|
+
attr_accessor :sockname
|
19
|
+
|
20
|
+
def initialize(sockname = nil)
|
21
|
+
@sockname = sockname || "/tmp/snailgun#{$$}"
|
22
|
+
File.delete(@sockname) rescue nil
|
23
|
+
@socket = UNIXServer.open(@sockname)
|
24
|
+
yield self if block_given?
|
25
|
+
end
|
26
|
+
|
27
|
+
def run
|
28
|
+
while client = @socket.accept
|
29
|
+
pid = fork do
|
30
|
+
rubylib = nil
|
31
|
+
begin
|
32
|
+
STDIN.reopen(client.recv_io)
|
33
|
+
STDOUT.reopen(client.recv_io)
|
34
|
+
STDERR.reopen(client.recv_io)
|
35
|
+
nbytes = client.read(4).unpack("N").first
|
36
|
+
args, env, cwd, pgid = Marshal.load(client.read(nbytes))
|
37
|
+
Dir.chdir(cwd)
|
38
|
+
if rubylib = env['RUBYLIB']
|
39
|
+
rubylib.split(/:/).each do |path|
|
40
|
+
$LOAD_PATH.unshift path
|
41
|
+
end
|
42
|
+
end
|
43
|
+
begin
|
44
|
+
Process.setpgid(0, pgid)
|
45
|
+
rescue Errno::EPERM
|
46
|
+
end
|
47
|
+
exit_status = 0
|
48
|
+
$SNAILGUN_EXIT = lambda {
|
49
|
+
begin
|
50
|
+
client.write [exit_status].pack("C")
|
51
|
+
rescue Errno::EPIPE
|
52
|
+
end
|
53
|
+
}
|
54
|
+
#This doesn't work in 1.8.6:
|
55
|
+
#Thread.new { client.read(1); Thread.main.raise Interrupt }
|
56
|
+
Thread.new { client.read(1); exit 1 }
|
57
|
+
start_ruby(args)
|
58
|
+
rescue SystemExit => e
|
59
|
+
exit_status = e.status
|
60
|
+
raise # for the benefit of Test::Unit
|
61
|
+
rescue Exception => e
|
62
|
+
STDERR.puts "#{e}\n\t#{e.backtrace.join("\n\t")}"
|
63
|
+
exit 1
|
64
|
+
ensure
|
65
|
+
$LOAD_PATH.shift if rubylib
|
66
|
+
end
|
67
|
+
end
|
68
|
+
Process.detach(pid) if pid && pid > 0
|
69
|
+
client.close
|
70
|
+
end
|
71
|
+
ensure
|
72
|
+
File.delete(@sockname) rescue nil
|
73
|
+
end
|
74
|
+
|
75
|
+
# Process the received ruby command line. (TODO: implement more options)
|
76
|
+
def start_ruby(args)
|
77
|
+
e = []
|
78
|
+
OptionParser.new do |opts|
|
79
|
+
opts.on("-e EXPR") do |v|
|
80
|
+
e << v
|
81
|
+
end
|
82
|
+
opts.on("-I DIR") do |v|
|
83
|
+
v.split(/:/).each do |path|
|
84
|
+
$:.unshift path
|
85
|
+
end
|
86
|
+
end
|
87
|
+
opts.on("-r LIB") do |v|
|
88
|
+
require v
|
89
|
+
end
|
90
|
+
opts.on("--dump_requires") do |v|
|
91
|
+
require File.dirname(__FILE__) + "/require_timings.rb"
|
92
|
+
end
|
93
|
+
opts.on("-KU") do |v|
|
94
|
+
$KCODE = 'u' if RUBY_VERSION < "1.9"
|
95
|
+
end
|
96
|
+
end.order!(args)
|
97
|
+
|
98
|
+
ARGV.replace(args)
|
99
|
+
if !e.empty?
|
100
|
+
$0 = '-e'
|
101
|
+
e.each { |expr| eval(expr, TOPLEVEL_BINDING) }
|
102
|
+
elsif ARGV.empty?
|
103
|
+
$0 = '-'
|
104
|
+
eval(STDIN.read, TOPLEVEL_BINDING)
|
105
|
+
else
|
106
|
+
cmd = ARGV.shift
|
107
|
+
$0 = cmd
|
108
|
+
load(cmd)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.shell
|
113
|
+
shell_opts = ENV['SNAILGUN_SHELL_OPTS']
|
114
|
+
args = shell_opts ? Shellwords.shellwords(shell_opts) : []
|
115
|
+
system(ENV['SHELL'] || 'bash', *args)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Interactive mode (start a subshell with SNAILGUN_SOCK set up,
|
119
|
+
# and terminate the snailgun server when the subshell exits)
|
120
|
+
def interactive!
|
121
|
+
ENV['SNAILGUN_SOCK'] = @sockname
|
122
|
+
pid = Process.fork {
|
123
|
+
STDERR.puts "Snailgun starting on #{sockname} - 'exit' to end"
|
124
|
+
run
|
125
|
+
}
|
126
|
+
self.class.shell
|
127
|
+
Process.kill('TERM',pid)
|
128
|
+
# TODO: wait a few secs for it to die, 'KILL' if required
|
129
|
+
STDERR.puts "Snailgun ended"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
data/ruby-1.9.2-p0.patch
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: Makefile
|
2
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: ancdata.o
|
3
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: basicsocket.o
|
4
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: constants.o
|
5
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: constdefs.c
|
6
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: constdefs.h
|
7
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: extconf.h
|
8
|
+
diff -u socket/extconf.rb /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket/extconf.rb
|
9
|
+
--- socket/extconf.rb 2010-05-19 15:48:50.000000000 +0200
|
10
|
+
+++ /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket/extconf.rb 2010-10-24 10:44:17.000000000 +0200
|
11
|
+
@@ -117,7 +117,7 @@
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
-if (have_func("sendmsg") | have_func("recvmsg")) && /64-darwin/ !~ RUBY_PLATFORM
|
16
|
+
+if have_func("sendmsg") | have_func("recvmsg")
|
17
|
+
# CMSG_ macros are broken on 64bit darwin, because of use of __DARWIN_ALIGN.
|
18
|
+
have_struct_member('struct msghdr', 'msg_control', ['sys/types.h', 'sys/socket.h'])
|
19
|
+
have_struct_member('struct msghdr', 'msg_accrights', ['sys/types.h', 'sys/socket.h'])
|
20
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: init.o
|
21
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: ipsocket.o
|
22
|
+
Common subdirectories: socket/lib and /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket/lib
|
23
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: mkmf.log
|
24
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: option.o
|
25
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: raddrinfo.o
|
26
|
+
diff -u socket/rubysocket.h /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket/rubysocket.h
|
27
|
+
--- socket/rubysocket.h 2010-04-28 09:16:30.000000000 +0200
|
28
|
+
+++ /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket/rubysocket.h 2010-10-24 10:43:51.000000000 +0200
|
29
|
+
@@ -138,6 +138,17 @@
|
30
|
+
};
|
31
|
+
#endif
|
32
|
+
|
33
|
+
+#if defined __APPLE__ && defined __MACH__
|
34
|
+
+/*
|
35
|
+
+ * CMSG_ macros are broken on 64bit darwin, because __DARWIN_ALIGN
|
36
|
+
+ * aligns up to __darwin_size_t which is 64bit, but CMSG_DATA is
|
37
|
+
+ * 32bit-aligned.
|
38
|
+
+ */
|
39
|
+
+#undef __DARWIN_ALIGNBYTES
|
40
|
+
+#define __DARWIN_ALIGNBYTES (sizeof(unsigned int) - 1)
|
41
|
+
+#endif
|
42
|
+
+
|
43
|
+
+
|
44
|
+
#if defined(_AIX)
|
45
|
+
#ifndef CMSG_SPACE
|
46
|
+
# define CMSG_SPACE(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + _CMSG_ALIGN(len))
|
47
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: socket.bundle
|
48
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: socket.o
|
49
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: sockssocket.o
|
50
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: tcpserver.o
|
51
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: tcpsocket.o
|
52
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: udpsocket.o
|
53
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: unixserver.o
|
54
|
+
Only in /Users/thieso/.rvm/src/ruby-1.9.2-p0/ext/socket: unixsocket.o
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tmp8-snailgun
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 1.2.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Brian Candler
|
13
|
+
- Sebastian Korfmann
|
14
|
+
- Thies C. Arntzen
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2010-12-01 00:00:00 +01:00
|
20
|
+
default_executable:
|
21
|
+
dependencies: []
|
22
|
+
|
23
|
+
description: Snailgun accelerates the startup of Ruby applications which require large numbers of libraries
|
24
|
+
email:
|
25
|
+
- b.candler@pobox.com
|
26
|
+
- dev@tmp8.de
|
27
|
+
executables:
|
28
|
+
- fautotest
|
29
|
+
- fconsole
|
30
|
+
- fcucumber
|
31
|
+
- frake
|
32
|
+
- fruby
|
33
|
+
- snailgun
|
34
|
+
- snailgun_ruby
|
35
|
+
extensions: []
|
36
|
+
|
37
|
+
extra_rdoc_files:
|
38
|
+
- README.markdown
|
39
|
+
files:
|
40
|
+
- bin/fautotest
|
41
|
+
- bin/fconsole
|
42
|
+
- bin/fcucumber
|
43
|
+
- bin/frake
|
44
|
+
- bin/fruby
|
45
|
+
- bin/snailgun
|
46
|
+
- bin/snailgun_ruby
|
47
|
+
- lib/snailgun/server.rb
|
48
|
+
- lib/snailgun/require_timings.rb
|
49
|
+
- lib/snailgun/client.rb
|
50
|
+
- lib/snailgun/require_preload.rb
|
51
|
+
- README.markdown
|
52
|
+
- README-snowleopard
|
53
|
+
- ruby-1.9.2-p0.patch
|
54
|
+
has_rdoc: true
|
55
|
+
homepage: http://github.com/candlerb/snailgun
|
56
|
+
licenses: []
|
57
|
+
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options:
|
60
|
+
- --inline-source
|
61
|
+
- --charset=UTF-8
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
version: "0"
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
version: "0"
|
80
|
+
requirements: []
|
81
|
+
|
82
|
+
rubyforge_project: snailgun
|
83
|
+
rubygems_version: 1.3.7
|
84
|
+
signing_key:
|
85
|
+
specification_version: 2
|
86
|
+
summary: Command-line startup accelerator
|
87
|
+
test_files: []
|
88
|
+
|