Ruby Code Performance Tweaks
- 2010-05-04
- Kurt Stephens – kurt@enovafinancial.com
- Enova Financial
- http://kurtstephens.com/pub/ruby/ruby_code_tweaks/
- http://github.com/kstephens/ruby_code_tweaks/
Start a ruby process N times.
  n.times do
    # SOLUTION?
  end
system("ruby ...")system("ruby ...")  n.times do
    system("#{$platform_cmd_line} -e 'exit 0'") or 
      raise "failed"    
  end

Yield to a block N times.
  40000.times do
    # SOLUTION?
  end
for i in 1..nn.times1.upto(n)(1..n).eachfor i in 1..n  40000.times do
    for i in 1 .. n do
      n
    end    
  end
n.times  40000.times do
    n.times do
      n
    end    
  end
1.upto(n)  40000.times do
    1.upto(n) do
      n
    end    
  end
(1..n).each  40000.times do
    (1 .. n).each do
      n
    end    
  end




Return a value from a method.
  n.times do
    x = true
    # SOLUTION? x
    x = false
    # SOLUTION? x
  end
explicit returnfall throughexplicit returndef sol_1  x
  if x
    return 1
  else
    return 2
  end  
end
  n.times do
    x = true
    sol_1 x
    x = false
    sol_1 x
  end
fall throughdef sol_2  x
  if x
    1
  else
    2
  end  
end
  n.times do
    x = true
    sol_2 x
    x = false
    sol_2 x
  end


Get first element of Array.
  array = [ :thing ]
  n.times do
    # SOLUTION?
  end
array[0]array.firstarray[0]  array = [ :thing ]
  n.times do
    array[0]    
  end
array.first  array = [ :thing ]
  n.times do
    array.first    
  end


array[0] is optimized on some platforms.array.first should be optimized on all platforms.Get last element of Array.
  array = [ :thing ]
  n.times do
    # SOLUTION?
  end
array[-1]array.lastarray[-1]  array = [ :thing ]
  n.times do
    array[-1]    
  end
array.last  array = [ :thing ]
  n.times do
    array.last    
  end


array[-1] is optimized on some platforms.array.last should be optimized on all platforms.Build a String from parts.
  foo = "foo"
  bar = 42
  n.times do
    # SOLUTION?
  end
String#+String InterpolationString#+  foo = "foo"
  bar = 42
  n.times do
    "abc" + foo + "123" + bar.to_s    
  end
String Interpolation  foo = "foo"
  bar = 42
  n.times do
    "abc#{foo}123#{bar}"    
  end


Output a String and Integer in a simple format
  foobar = "foobar"
  n.times do
    # SOLUTION?
  end
String#%String interpolationSprintfCompiler cachedString#%  foobar = "foobar"
  n.times do
    "%s, %d" % [ foobar, n ]    
  end
String interpolation  foobar = "foobar"
  n.times do
    "#{foobar}, #{n}"    
  end
SprintfCompiler cached  foobar = "foobar"
  n.times do
    SprintfCompiler.fmt("%s, %d", [ foobar, n ])    
  end



Construct a Symbol from a String.
  foobar = "foobar"
  n.times do
    # SOLUTION?
  end
String#to_symDynamic SymbolString#to_sym  foobar = "foobar"
  n.times do
    "#{foobar}123".to_sym    
  end
Dynamic Symbol  foobar = "foobar"
  n.times do
    :"#{foobar}123"    
  end


Enumerate elements while using a temporary or block variable.
  array = (0 ... n).to_a.sort_by{|x| rand}
  100000.times do
    # SOLUTION?
  end
Array#injectLocal variableArray#inject  array = (0 ... n).to_a.sort_by{|x| rand}
  100000.times do
    array.inject({ }) { | hash, x | hash[x] = true; hash }    
  end
Local variable  array = (0 ... n).to_a.sort_by{|x| rand}
  100000.times do
    hash = { }
    array.each { | x | hash[x] = true }
    hash    
  end


Accumulate String parts of size N into one larger String.
  parts = (0 ... 100).to_a.map{"a" * n}
  str = ''
  100.times do
    # SOLUTION?
  end
str += xstr << xstr += x  parts = (0 ... 100).to_a.map{"a" * n}
  str = ''
  100.times do
    parts.each do | x |
      str += x
    end    
  end
  str += x
is the same as:
  str = (str + x)
str << x  parts = (0 ... 100).to_a.map{"a" * n}
  str = ''
  100.times do
    parts.each do | x |
      str << x
    end    
  end


Accumulate String parts of size N into one larger String.
  parts = (0 ... 100).to_a.map{"a" * n}
  10000.times do
    # SOLUTION?
  end
str << xparts.joinstr << x  parts = (0 ... 100).to_a.map{"a" * n}
  10000.times do
    str = ''
    parts.each do | x |
      str << x
    end    
  end
parts.join  parts = (0 ... 100).to_a.map{"a" * n}
  10000.times do
    str = parts.join("")    
  end


Is a value in a short, constant set?
  # n = 2
  x == 0 || x == 1
  [ 0, 1 ].include?(x)
  case x
  when 0, 1
    true
  end
  # ETC... TIMTOWTI!
x == y1 || ...[ ... ].include?(x)array.include?(x)case x; when y1, y2 ...case x; when *arrayhash.key?(x)x == y1 || ...  @array = (0 ... n).to_a.sort_by{|x| rand}
  try    = (0 ... 1000).to_a.map{|x| rand(n + n)}.sort_by{|x| rand}
  x == 0                 # n == 1
  x == 0 || x == 1       # n == 2
  ...
[ ... ].include?(x)  @array = (0 ... n).to_a.sort_by{|x| rand}
  try    = (0 ... 1000).to_a.map{|x| rand(n + n)}.sort_by{|x| rand}
  [ 0, 1 ].include?(x)     # n == 2
array.include?(x)  @array = (0 ... n).to_a.sort_by{|x| rand}
  try    = (0 ... 1000).to_a.map{|x| rand(n + n)}.sort_by{|x| rand}
  ARRAY = [ 0, 1 ].freeze   # n == 2
  ...
  ARRAY.include?(x)
case x; when y1, y2 ...  @array = (0 ... n).to_a.sort_by{|x| rand}
  try    = (0 ... 1000).to_a.map{|x| rand(n + n)}.sort_by{|x| rand}
  case x
  when 0, 1           # n == 2
    true
  end
case x; when *array  @array = (0 ... n).to_a.sort_by{|x| rand}
  try    = (0 ... 1000).to_a.map{|x| rand(n + n)}.sort_by{|x| rand}
  ARRAY = [ 0, 1 ].freeze
  ...
  case x
  when *ARRAY
    true
  end
hash.key?(x)  @array = (0 ... n).to_a.sort_by{|x| rand}
  try    = (0 ... 1000).to_a.map{|x| rand(n + n)}.sort_by{|x| rand}
  HASH = { 0 => true, 1 => true }.freeze
  ...
  HASH.key?(x)






===, not ==.x == y when n == 1.Is an element in a Array?
  array = (0 ... n).to_a.sort_by{|x| rand}
  try   = (0 ... 2000).to_a.sort_by{|x| rand}
  100.times do
    try.each do | x |
      # SOLUTION?
    end
  end
Array#include?case x; when *arrayhash.key?(x)Array#include?  array = (0 ... n).to_a.sort_by{|x| rand}
  try   = (0 ... 2000).to_a.sort_by{|x| rand}
  100.times do
    try.each do | x |
      array.include?(x)      
    end
  end
case x; when *array  array = (0 ... n).to_a.sort_by{|x| rand}
  try   = (0 ... 2000).to_a.sort_by{|x| rand}
  100.times do
    try.each do | x |
      case x
      when *array
        true
      end      
    end
  end
hash.key?(x)  array = (0 ... n).to_a.sort_by{|x| rand}
  try   = (0 ... 2000).to_a.sort_by{|x| rand}
  100.times do
    try.each do | x |
      hash.key?(x)      
    end
  end



#=== operator.Array#include? is slower than MRI 1.8.6.Is a value in a constant set?
  # n = 2 
  array = [ :foo, :bar ] 
  hash  = { :foo => true, :bar => true }
  set   = Set.new([ :foo, :bar ])
  ...
  array.include?(x)
  hash.key?(x)
  set.include?(x)
  ! (array & [ x ]).empty?     # <== WTF?
array.include?(x)hash.key?(x)set.include?(x)!(array&[x]).empty?array.include?(x)  array = (0 ... n).to_a.sort_by{|x| rand}
  try   = (0 ... 1000).to_a.map{|x| rand(n + n)}.sort_by{|x| rand}
  1000.times do
    try.each do | x |
      array.include? x      
    end
  end
hash.key?(x)  array = (0 ... n).to_a.sort_by{|x| rand}
  try   = (0 ... 1000).to_a.map{|x| rand(n + n)}.sort_by{|x| rand}
  1000.times do
    try.each do | x |
      hash.key?(x)      
    end
  end
set.include?(x)  array = (0 ... n).to_a.sort_by{|x| rand}
  try   = (0 ... 1000).to_a.map{|x| rand(n + n)}.sort_by{|x| rand}
  1000.times do
    try.each do | x |
      set.include?(x)      
    end
  end
!(array&[x]).empty?  array = (0 ... n).to_a.sort_by{|x| rand}
  try   = (0 ... 1000).to_a.map{|x| rand(n + n)}.sort_by{|x| rand}
  1000.times do
    try.each do | x |
      ! (array & [ x ]).empty?      
    end
  end









!(Array&[x]).empty? performs “too well”. (!!!)Evaluate a dynamic expression
  x = 10
  expr = "x * 2"
  eval(expr, binding)
evalcached lambdaeval  exprs = (0 ... 100).to_a.sort_by{|y| rand}.map{|y| "x * #{y}"}
  x = 10
  n.times do 
    exprs.each do | expr |
      eval(expr, binding)      
    end
  end
cached lambda  exprs = (0 ... 100).to_a.sort_by{|y| rand}.map{|y| "x * #{y}"}
  x = 10
  n.times do 
    exprs.each do | expr |
      p = lambdas[expr] ||= eval(%Q{lambda{|x| #{expr}}})
      p.call(x)      
    end
  end







http://github.com/kstephens/ruby_code_tweaks