M
Martin Jansson
I recently started to learn Ruby. I thought that the obviously flawed
Random
benchmark at http://shootout.alioth.debian.org would make a good first
project.
I need some help with profiling as my system is a lot different from the
shootout setup. My system is a iBook G4 with Mac OS 10.3 and Ruby 1.8. They
use Linux on AMD with Ruby 1.9.
The original implementation have two eyecatching flaws:
1) It use Floats instead of Fixnum
2) It uses a really costly way to get the first program parameter.
After I corrected these two misstakes it used 30% less time and
considerably less memory (at least half as much, hard to measure).
Then I started from scratch and wrote my own version, doing a lot of
experimentation. This is the result:
# Code start
module Kernel
$srandom = 42
def random(max)
(max * ($srandom = ($srandom * 3877 + 29573) % 139968)).quo(139968)
end
end
($*.first.to_i-1).times do
random(100)
end
printf "%.9f\n", random(100)
# Code end
The most important qualities is (in order of saved time):
* Use Fixnum for integer arithmetics. Much faster and with better
precision.
* Use ARGV.first instead of ARGV.shift to get first parameter
* Use literals instead of constants. Ruby constants is no real constants,
they are global variables with A LOT of overhead. The specification
C-program use literals. An alternative would be to use
local variables.
* Use $* instead of ARGV. Sigh. Ruby constants are really, reeeally
slooooow.
* Use times as iterator. As do the original solution.
* Use a global variable to hold the seed. As do the original solution.
I can't find a sane way to keep the seed between method calls without
consuming a lot of precious time.
* Wraped the function in module Kernel. For some odd reason this makes the
program somewhat faster. I really don't like it, but...
I've also tried a nice Simula flavoured version an, not so nice,
"oo"-version and a lot of really wacky versions.
They are a lot faster then the original code, but slower then the above
version.
Random
benchmark at http://shootout.alioth.debian.org would make a good first
project.
I need some help with profiling as my system is a lot different from the
shootout setup. My system is a iBook G4 with Mac OS 10.3 and Ruby 1.8. They
use Linux on AMD with Ruby 1.9.
The original implementation have two eyecatching flaws:
1) It use Floats instead of Fixnum
2) It uses a really costly way to get the first program parameter.
After I corrected these two misstakes it used 30% less time and
considerably less memory (at least half as much, hard to measure).
Then I started from scratch and wrote my own version, doing a lot of
experimentation. This is the result:
# Code start
module Kernel
$srandom = 42
def random(max)
(max * ($srandom = ($srandom * 3877 + 29573) % 139968)).quo(139968)
end
end
($*.first.to_i-1).times do
random(100)
end
printf "%.9f\n", random(100)
# Code end
The most important qualities is (in order of saved time):
* Use Fixnum for integer arithmetics. Much faster and with better
precision.
* Use ARGV.first instead of ARGV.shift to get first parameter
* Use literals instead of constants. Ruby constants is no real constants,
they are global variables with A LOT of overhead. The specification
C-program use literals. An alternative would be to use
local variables.
* Use $* instead of ARGV. Sigh. Ruby constants are really, reeeally
slooooow.
* Use times as iterator. As do the original solution.
* Use a global variable to hold the seed. As do the original solution.
I can't find a sane way to keep the seed between method calls without
consuming a lot of precious time.
* Wraped the function in module Kernel. For some odd reason this makes the
program somewhat faster. I really don't like it, but...
I've also tried a nice Simula flavoured version an, not so nice,
"oo"-version and a lot of really wacky versions.
They are a lot faster then the original code, but slower then the above
version.