J
Joel VanderWerf
If you use ruby 1.8 for quick command line tasks, and you use gems, you
may notice that the interpreter has an execution overhead that is small
but noticeable and irritating when repeated often enough.
$ time RUBYOPT='' ruby -e 1
ruby -e 1 0.01s user 0.00s system 105% cpu 0.011 total
$ time RUBYOPT='rubygems' ruby -e 1
RUBYOPT='rubygems' ruby -e 1 0.58s user 0.06s system 94% cpu 0.675 total
This is greatly improved in 1.9, which has gems built in.
$ time RUBYOPT='rubygems' ruby19 -e 1
RUBYOPT='rubygems' ruby19 -e 1 0.02s user 0.01s system 48% cpu 0.067 total
An order of magnitude improvement makes the delay much more acceptable,
but if you're working with 1.8, that's not an option.
So here's a hack for 1.8 that restores the speed of bare-metal ruby but
still lets you use gems. What it does is redefine Kernel#require to try
loading things without rubygems, but fall back to using rubygems when
there is a load failure.
Put the file in a dir on your $LOAD_PATH, and set RUBYOPT to reference
it, as shown below. *Note:* I haven't tested this widely yet. It may
break libraries that do their own hacking with require or use LOAD_ERROR
for their own devious purposes. I advise not using this hack in
production code without careful testing.
$ cat gem-fallback.rb
module Kernel
req = method :require
define_method :require do |*args|
begin
req.call(*args)
rescue LoadError
Kernel.module_eval do
define_method
require, &req)
end
require 'rubygems'
require(*args)
end
end
end
$ time RUBYOPT='rgem-fallback' ruby -e 1
RUBYOPT='rgem-fallback' ruby -e 1 0.01s user 0.00s system 71% cpu 0.011
total
$ time RUBYOPT='rgem-fallback' ruby -e "require 'tagz'"
RUBYOPT='rgem-fallback' ruby -e "require 'tagz'" 0.60s user 0.07s
system 79% cpu 0.850 total
may notice that the interpreter has an execution overhead that is small
but noticeable and irritating when repeated often enough.
$ time RUBYOPT='' ruby -e 1
ruby -e 1 0.01s user 0.00s system 105% cpu 0.011 total
$ time RUBYOPT='rubygems' ruby -e 1
RUBYOPT='rubygems' ruby -e 1 0.58s user 0.06s system 94% cpu 0.675 total
This is greatly improved in 1.9, which has gems built in.
$ time RUBYOPT='rubygems' ruby19 -e 1
RUBYOPT='rubygems' ruby19 -e 1 0.02s user 0.01s system 48% cpu 0.067 total
An order of magnitude improvement makes the delay much more acceptable,
but if you're working with 1.8, that's not an option.
So here's a hack for 1.8 that restores the speed of bare-metal ruby but
still lets you use gems. What it does is redefine Kernel#require to try
loading things without rubygems, but fall back to using rubygems when
there is a load failure.
Put the file in a dir on your $LOAD_PATH, and set RUBYOPT to reference
it, as shown below. *Note:* I haven't tested this widely yet. It may
break libraries that do their own hacking with require or use LOAD_ERROR
for their own devious purposes. I advise not using this hack in
production code without careful testing.
$ cat gem-fallback.rb
module Kernel
req = method :require
define_method :require do |*args|
begin
req.call(*args)
rescue LoadError
Kernel.module_eval do
define_method
end
require 'rubygems'
require(*args)
end
end
end
$ time RUBYOPT='rgem-fallback' ruby -e 1
RUBYOPT='rgem-fallback' ruby -e 1 0.01s user 0.00s system 71% cpu 0.011
total
$ time RUBYOPT='rgem-fallback' ruby -e "require 'tagz'"
RUBYOPT='rgem-fallback' ruby -e "require 'tagz'" 0.60s user 0.07s
system 79% cpu 0.850 total