-
Divide & Conquer?
After reading that on embedded systems that when one wishes to divide a number by another, it is more perfomant to multiply by the divisor’s reciprocal instead. If I recall correctly this something to do with some embedded platforms lacking hardware to perform division and so it is emulated in some way, i.e. a lot slower.
I was wondering what the performance difference between dividing by an integer or multiplying by its reciprocal in Ruby is.
Benchmark code:
require 'benchmark' Benchmark.bmbm do |x| x.report("divide:") { 9999999.times { 999999999 / 8 } } x.report("multiply:") { 9999999.times { 999999999 * 0.125 } } endRuby 1.8.7
Rehearsal --------------------------------------------- divide: 2.160000 0.020000 2.180000 ( 2.348516) multiply: 2.380000 0.010000 2.390000 ( 2.542357) ------------------------------------ total: 4.570000sec user system total real divide: 2.230000 0.010000 2.240000 ( 2.406294) multiply: 2.420000 0.020000 2.440000 ( 2.594445)
Ruby 1.9.1
Rehearsal --------------------------------------------- divide: 1.110000 0.000000 1.110000 ( 1.137086) multiply: 2.890000 0.020000 2.910000 ( 2.953284) ------------------------------------ total: 4.020000sec user system total real divide: 1.110000 0.010000 1.120000 ( 1.125234) multiply: 2.860000 0.010000 2.870000 ( 2.891654)Ruby 1.9.2 preview release
Rehearsal --------------------------------------------- divide: 1.160000 0.000000 1.160000 ( 1.243541) multiply: 2.530000 0.020000 2.550000 ( 2.723876) ------------------------------------ total: 3.710000sec user system total real divide: 1.160000 0.000000 1.160000 ( 1.196763) multiply: 2.490000 0.020000 2.510000 ( 2.591883)I tested on a new MacBook Pro 2.53 GHz 4GB. As you can see in 1.8.7 the difference is very small, but on the 1.9.x branch with a different VM, division has been significantly optimised while nominally speaking at least, multiplication performance appears to have slightly deteriorate.
Don’t even think about multiplying/dividing a fixnum to/by a float or vice versa if your code may be deployed on JRuby.JRuby 1.4
Rehearsal --------------------------------------------- divide: 1.960000 0.000000 1.960000 ( 1.783000) multiply: 21.506000 0.000000 21.506000 ( 21.505000) ----------------------------------- total: 23.466000sec user system total real divide: 1.962000 0.000000 1.962000 ( 2.079000) multiply: 23.535000 0.000000 23.535000 ( 23.535000)It turns out JRuby is an absolute dog when using floats and fixnums together in divide/multiply operations.Forget about it too if you’re looking at MacRuby…MacRuby 0.5
Rehearsal --------------------------------------------- divide: 0.420000 0.010000 0.430000 ( 0.444890) multiply: 0.420000 0.000000 0.420000 ( 0.434119) ------------------------------------ total: 0.850000sec user system total real divide: 0.420000 0.000000 0.420000 ( 0.427087) multiply: 0.420000 0.000000 0.420000 ( 0.426598)Since MacRuby is a total BEAST across the board. Insane performance!
s
EDIT: These benchmarks were run in IRB. Using JRuby IRB enables ObjectSpace (FWIW Charles Nutter recently made a commit to trunk so that IRB doesn’t require ObjectSpace), which causes an incredible performance hit in JRuby. Running the benchmark as a script yields very impressive performance:
Rehearsal --------------------------------------------- divide: 1.178000 0.000000 1.178000 ( 1.097000) multiply: 1.078000 0.000000 1.078000 ( 1.078000) ------------------------------------ total: 2.256000sec user system total real divide: 1.019000 0.000000 1.019000 ( 1.019000) multiply: 1.022000 0.000000 1.022000 ( 1.022000)
Mon05Apr