tmp8-snailgun 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|