http://refactormycode.com
Read this blog, it will make you smile!
I did some testing on the refactorings suggested in:
http://refactormycode.com/codes/2-ruby-simple-loop
testing.rb
def prof(t = 1, output = :puts)
starting_time = Time.now
t.times { yield }
dlta = (Time.now - starting_time).to_f/t
case output
when :ret
"### time: #{dlta.to_s}(s) . req/s: #{(1/dlta)}"
else
puts "### time: #{dlta.to_s}(s) . req/s: #{(1/dlta)}"
end
end
times = []
times << ["(1..10).each do |i|
puts i
end",
prof(1000,:ret) {
(1..10).each do |i|
puts i
end
}]
times << ["for i in (1..10)
puts i
end
",prof(1000,:ret){
for i in (1..10)
puts i
end
}]
times << ["(1..10).each { |i| puts i }",prof(1000,:ret){
(1..10).each { |i| puts i }
}]
#times << ["puts (1..10).to_a * '\n'",prof(1000,:ret){
# puts (1..10).to_a * "\n"
#}]
#times << ["puts (1..10).to_a",prof(1000,:ret){
# puts (1..10).to_a
#}]
times << ["1.upto(10) { |i| puts i }",prof(1000,:ret){
1.upto(10) { |i| puts i }
}]
times << ["puts 1,2,3,4,5,6,7,8,9,10",prof(1000,:ret){
puts 1,2,3,4,5,6,7,8,9,10
}]
times << ["10.times {|i| p i+1}",prof(1000,:ret){
10.times {|i| p i+1}
}]
puts '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
times.collect { |t|
puts t
puts '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
}
Two of the suggestions:
- puts (1..10).to_a
- puts (1..10).to_a * "\n"
And the results are ...
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
(1..10).each do |i|
puts i
end
### time: 0.000165467(s) . req/s: 6043.50112106946
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
for i in (1..10)
puts i
end
### time: 0.00018765(s) . req/s: 5329.07007727152
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
(1..10).each { |i| puts i }
### time: 0.00020241(s) . req/s: 4940.46736821303
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1.upto(10) { |i| puts i }
### time: 0.000216612(s) . req/s: 4616.54940631175
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
puts 1,2,3,4,5,6,7,8,9,10
### time: 0.000164026(s) . req/s: 6096.59444234451
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
10.times {|i| p i+1}
### time: 0.000208756(s) . req/s: 4790.28147693958
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

6 comments:
so what's the final final result? better to write more code and it runs faster? death to refractoring? write more code, it's better for ya?
;)
I think that the thing most common for the two highest ranked results:
{ (1..10).each do |i|
puts i
end }
and
{ puts 1,2,3,4,5,6,7,8,9,10 }
is the simplicity of it's code.
my conclusions are:
1. SIMPLE = GOOD PERFORMANCE
2. SIMPLE != SHORT
3. SHORT != GOOD PERFORMANCE
hence:
* WRITE SIMPLE CODE!
Isn't the real lesson here to stop paying so much attention to brevity as it relates to performance?????
THe total difference between the slowest and the fastest loop is 0.00005! So write your code for readability and maintainability, super short but obscure notation won't save you performance time but will cost you maintenance time.
i totally agree.
Hi,
I ran the tests under ruby1.8.7 and ruby1.9.0 with some modification to the code (to see how the code caching affects the performance):
without further ado, here's the results:
bensch@buzzlightyear:~/code
$ ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]
bensch@buzzlightyear:~/code
$ ruby perftest.rb 1000
.... print statements ...
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
round 1
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
(1..10).each do |i|
puts i
end
### time: 0.0001870918(s) . req/s: 5344.9696886769
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
for i in (1..10)
puts i
end
### time: 0.0001321788(s) . req/s: 7565.50974891586
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
(1..10).each { |i| puts i }
### time: 0.0001255472(s) . req/s: 7965.1318388622
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1.upto(10) { |i| puts i }
### time: 0.0001290822(s) . req/s: 7747.0015230605
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
puts 1,2,3,4,5,6,7,8,9,10
### time: 0.0001403234(s) . req/s: 7126.39517001441
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
10.times {|i| p i+1}
### time: 0.0001296322(s) . req/s: 7714.13275405339
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
p *(1...11)
### time: 0.0001263086(s) . req/s: 7917.117282592
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
round 2
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
(1..10).each do |i|
puts i
end
### time: 0.0001381384(s) . req/s: 7239.11671193528
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
for i in (1..10)
puts i
end
### time: 0.0001273014(s) . req/s: 7855.37315379092
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
(1..10).each { |i| puts i }
### time: 0.0001195598(s) . req/s: 8364.0153295673
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1.upto(10) { |i| puts i }
### time: 0.0001238354(s) . req/s: 8075.23535273436
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
puts 1,2,3,4,5,6,7,8,9,10
### time: 0.0001248374(s) . req/s: 8010.41995427652
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
10.times {|i| p i+1}
### time: 0.000120458(s) . req/s: 8301.6487074333
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
p *(1...11)
### time: 0.0001243884(s) . req/s: 8039.33485759122
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
bensch@buzzlightyear:~/code
$ ruby1.9 -v
ruby 1.9.0 (2008-06-20 revision 17482) [i486-linux]
bensch@buzzlightyear:~/code
$ ruby1.9 perftest.rb 5000
... print here ...
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
round 1
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
(1..10).each do |i|
puts i
end
### time: 0.00037681948(s) . req/s: 2653.79061613269
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
for i in (1..10)
puts i
end
### time: 0.000236757456(s) . req/s: 4223.73181776375
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
(1..10).each { |i| puts i }
### time: 0.000262516872(s) . req/s: 3809.27897083887
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1.upto(10) { |i| puts i }
### time: 0.0002385816(s) . req/s: 4191.43806563457
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
puts 1,2,3,4,5,6,7,8,9,10
### time: 0.00024351652(s) . req/s: 4106.49757971246
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
10.times {|i| p i+1}
### time: 0.000232166248(s) . req/s: 4307.25830569481
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
p *(1...11)
### time: 0.000243938672(s) . req/s: 4099.39101414802
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
round 2
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
(1..10).each do |i|
puts i
end
### time: 0.000238355264(s) . req/s: 4195.41814692207
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
for i in (1..10)
puts i
end
### time: 0.00023042488(s) . req/s: 4339.80913866593
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
(1..10).each { |i| puts i }
### time: 0.000230546216(s) . req/s: 4337.52510602907
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1.upto(10) { |i| puts i }
### time: 0.000231344432(s) . req/s: 4322.55918741973
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
puts 1,2,3,4,5,6,7,8,9,10
### time: 0.000238063504(s) . req/s: 4200.55986406047
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
10.times {|i| p i+1}
### time: 0.000230549824(s) . req/s: 4337.45722573182
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
p *(1...11)
### time: 0.00024032068(s) . req/s: 4161.10673455152
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Interesting points:
1) 1.8.7 is twice as fast as 1.9 in these tests.
2) There is a significant speed up between round 1 and round 2 for some of the tests.
3) once the code in the vm is warmed up, then the difference between the fastest version and slowest version is large but not huge (1.8.7 -> 1.15x faster, 1.9 -> 1.04x faster)
So write your code simply and keep it in cache so the VM can optimize it to maximum effect.
The code is at http://pastebin.ca/1324646
Cheers
ben
You are comparing 0.1ms with 0.2ms here; I doubt that time measurement is reliable for such small units. Run the code for (1..100000) and maybe you get interpretable results.
Besides, "puts" surely accounts for the most runtime here. Thus, you do not really compare the respective loop interpretation speed. Add the i up to get better results.
Post a Comment