Saturday, June 23, 2012

Timing a function call in Java, JRuby, and Python

Just for fun I thought I'd do a simple performance test in Java, Ruby, and Python.  For my test I'm going to calculate the greatest common factor of 12 and 30 (which is 6) a million times.  I'm running Java 1.7.0.03, JRuby 1.6.6, and Python 2.7.2.

I'm also on a Windows 7 machine with 4 GB of RAM and an Intel Core i3 CPU. I calculated the averages in LibreOffice's Calc, which conveniently rounded some of my numbers.  I'm also using SyntaxHighlighter to display source code.

I was hoping Python would come out on top, but logically it seemed like it would be Java, then Python and finally Ruby. I say that because Java uses primitive types and is compiled to bytecode. I picked Ruby to run the slowest because it's a true object-oriented language and is interpreted.


Java
public class MyTest {

  public static void GCF(int a, int b) {
    int x = a;

    while(((a % x) != 0) || ((b % x) != 0)) {
      x--;
    }
  }
 
  public static void main(String[] args) {   
    final int NUMBER_RUNS = 1000000;
    double average;
    long start, end, total = 0;
  
    for(int i = 0; i < NUMBER_RUNS; i++) {
      start = System.currentTimeMillis();
      GCF(12, 30);
      end = System.currentTimeMillis();
      total += (end - start);
    }

    System.out.println("Average: " + total/(double)NUMBER_RUNS);   
  }
}
Iteration 1 2 3 4 5
Time (Milliseconds) 3.10E-005 1.60E-005 4.80E-005 6.30E-005 4.60E-005

Iteration 6 7 8 9 10
Time (Milliseconds) 4.70E-005 4.80E-005 1.50E-005 3.20E-005 1.60E-005

Average: 3.62E-005

Etten, D. (2009, January 29). Why Many Java Performance Tests are Wrong.

mkyong (2009, January 20). While loop, For loop and Iterator Performance Test – Java.

Python
import timeit
def GCF(a, b):
  x = a

  while(((a % x) != 0) or ((b % x) != 0)):
    x -= 1

t = timeit.Timer(stmt = "GCF(12, 30)", \
  setup = "from __main__ import GCF")

print t.timeit()
Iteration 1 2 3 4 5
Time (Seconds) 1.50440505 1.4944670416 1.504301113 1.4949309084 1.4894804741

Iteration 6 7 8 9 10
Time (Seconds) 1.4979489294 1.4886595646 1.4888525217 1.4983733386 1.4911271048

Average: 1.4952546046

Mario. (2010, January 5). Let's timeit!, Mario


Edit 7/13/2012:

The Java and JRuby version both calculate the average time it takes to execute the statement a million times.  The Python version, however, just outputs the amount of time it takes to execute the statement a million times.  Therefore, dividing the average 1.4952546046 by a million and then multiplying by a 1000 (to convert to milliseconds) gives the result 0.001495255.  That's a little a better, but still slow.


JRuby
require "benchmark"
def GCF(a, b)
    x = a

    while(((a % x) != 0) or ((b % x) != 0)) do
        x -= 1
    end
end

NUMBER_RUNS = 1000000

time = Benchmark.realtime do
    (1..NUMBER_RUNS).each { GCF(12, 30) }
end

puts "Average: #{(time/NUMBER_RUNS)}"
Iteration 1 2 3 4 5
Time (Milliseconds) 6.71E-007 6.86E-007 6.71E-007 7.02E-007 6.71E-007

Iteration 6 7 8 9 10
Time (Milliseconds) 7.18E-007 6.86E-007 6.87E-007 6.71E-007 6.86E-007

Average: 6.85E-007

Skorkin, A. (2010, March 16). Timing Ruby Code – It Is Easy With Benchmark,,

Boy were my assumptions wrong.  Python's the slowest one out of the three.  I was even more surprised that JRuby out performed Java.

No comments:

Post a Comment