Joel VanderWerf wrote:
> 
> 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

An update, in case anyone uses this: the sinatra gem uses some black 
magic involving #caller, and the presence of this additional require 
method on the call stack will confuse sinatra into thinking it is not in 
"run" mode and it will not parse ARGV. You can fix this by setting a 
constant when loading sinatra, as in below. (To reiterate, I don't 
recommend this for production code. This is mostly for fast startup when 
using ruby from the command line. For production code, I am using the 
crown tool that I announced a few weeks ago[1].)

module Kernel
   req = method :require
   define_method :require do |*args|
     begin
       req.call(*args)
     rescue LoadError => ex
       Kernel.module_eval do
         define_method(:require, &req)
       end
       require 'rubygems'
       if args.grep(/sinatra/).any?
         pat = /gem-fallback.rb/
         if defined?(RUBY_IGNORE_CALLERS)
           RUBY_IGNORE_CALLERS << pat
         else
           RUBY_IGNORE_CALLERS = [pat]
         end
       end
       require(*args)
     end
   end
end

[1] http://github.com/vjoel/crown/tree/master

-- 
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407