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