I’ve been looking for a while for specifics on how one of my favorite
languages, Ruby, performs relative to its most comparable (and, to an
extent, rival) language, Python. However, I was never able to find any
specifics, or really, anything beyond hearsay or biased conjecture. So I
decided to do some research myself.
TL;DR
If you don’t want to read an entire lab thesis, skip to the bottom for a
conclusion, and number analyses.
So, I present to you: Ruby vs. Python; A speed test with actual numbers.
For the record, I used an Asus laptop with dual 5400RPM hard disks, and
an Intel Core i7-3630QM CPU with 4 cores, 8 threads, and a factory clock
speed of 2.40MHz, not overclocked, running Windows 8.1 64-Bit. (I would
usually be doing this on Fedora Linux, but Bill Gates went pretty
monkey-attack mode on secondary systems for Win 8.) I am also running
the stock, default interpreter for each language. Python was running
version 3.4.2, and Ruby on version 2.1.4.
Test 1: The ‘for’ Loop
The first test was a VERY simple one; an old fashioned ‘for’ loop. This
was just to test RAW speed of the interpreters, and the looping
structure.
Here’s the Ruby code I ran:
t = Time.now.to_f
for i in 1…1000000
puts i
end
puts "Elapsed time: ", Time.now.to_f - t
And the Python Equivalent:
import time
t = time.time()
for i in range(1, 1000000):
print(i)
print("Elapsed time: ", time.time() - t)
They printed out each value between 1 and 999,999, then spat out the
number of seconds it took. I did 4 tests for each language, with Python
going first for each set. (Python, Ruby, Python, Ruby…) The times were
very similar within each language, so there didn’t seem to be any
problems outside of the languages themselves.
Ruby average time: 69.49673 seconds
Python average time: 45.61045 seconds
Ruby to Python speed ratio: 1 : 0.6563
Python to Ruby speed ratio: 1 : 1.5237
Ruby’s time, as I had expected after what I had heard on some
programming forums, was noticeably slower, by about 50%. This wasn’t
enough to make me want to stop using Ruby by any means, but it
definitely was something to take into consideration for speed sensitive
tasks that you don’t want to write in C.
Test 2: Recursion and Subroutines
I decided that it would be good form to try another test, and see what
the results would be if I tried recursion. I knew it would be a better
gauge of method calling efficiency, resource management, and real-world
performance. I predicted that Python would still beat Ruby out, but by a
lesser margin, maybe 25% rather than 50, due to Ruby’s slightly simpler
design. So I wrote scripts that found the 40th number in the Fibonacci
Sequence. (Starting at 0, obviously)
Ruby Code:
def fibonacci(i)
if i < 2
return i
else
return fibonacci(i-2) + fibonacci(i-1)
end
end
t = Time.now.to_f
puts fibonacci(40)
puts "Elapsed time: ", Time.now.to_f - t
Python Code:
import time
def fibonacci(i):
if i < 2:
return i
else:
return fibonacci(i-2) + fibonacci(i-1)
t = time.time()
print(fibonacci(40))
print("Elapsed time: ", time.time() - t)
Again, they printed out the 40th Fibonacci number, and how many seconds
it took to figure it out. I decided to use ‘if’ statements with ‘return’
statements inside, rather than ‘return if’ statements to eliminate as
many variables between the languages as possible. This time, Ruby went
first for each test. (Ruby, Python, Ruby, Python…) And again, the
times were very similar within each language.
Ruby average time: 15.60163 seconds
Python average time: 54.91850 seconds
Ruby to Python speed ratio: 1 : 3.5200
Python to Ruby Speed ratio: 1 : 0.2841
I was VERY surprised by this test. Although Python was a full 50% faster
as far as raw speeds went in the ‘for’ loop test, Ruby BLASTED through
this test at 15 seconds, and left Python in the dust with 55 seconds,
almost a full minute! But the test had me scratching my head. How is it
possible that Ruby was almost 4 times faster than Python, despite a
slower raw speed? Simple architecture? Efficient subroutine calling?
Flawless resource management? More utilization of threads? Whatever the
case may be, I was pretty impressed by the MRI.
Conclusion
Python has a notably higher raw speed than Ruby, being 50% faster in a
simple ‘for’ loop test. However, neither are blazing fast, and C should
really be used for anything that speed-dependent. However, Ruby was
light-years ahead of Python when it came to the recursion test. This is
much heavier on the use of subroutines, resources, “multitasking,” value
returns, and real-world performance as a whole.
‘for’ Loop Test:
Ruby average time: 69.49673 seconds
Python average time: 45.61045 seconds
Ruby to Python speed ratio: 1 : 0.6563
Python to Ruby speed ratio: 1 : 1.5237
Recursion and Subroutine Test:
Ruby average time: 15.60163 seconds
Python average time: 54.91850 seconds
Ruby to Python speed ratio: 1 : 3.5200
Python to Ruby Speed ratio: 1 : 0.2841
Thanks, and I hope some of you find this useful.
-RJ