LL(Lightweight Language)の実行速度を比較してみた

久し振りにここへ書けるネタが…と思ったら,最後に書いてからもう3年経ってる!?
…というのはさておき.

「LLのPerl, Ruby, Pythonって,同じ処理させたら実行時間にどれくらいの違いが出るんだろう?」
と,気になったので調べてみた.
ついでに,コンパイラ型言語のC, Java, Fortranとも比べる事に.

で,手っ取り早く結果を示すと,処理の早い順は次のようになった.

Fortran < C < Java < Perl < Python < Ruby

やはりコンパイラ型言語の方が早いってのは当然だとして,
LLの中ではPerlが一番早く,次いでPythonRubyの順.

僕にとってこの結果は「ふぅん,そうなんだー」という感じ.
調べた方法やもう少し詳しい結果,各言語のソースプログラムが気になる人は,
このエントリの続きを参照の事!

今回,それぞれの言語でなるべく処理内容が同じくなる様にプログラム書いたんだけど,これが結構面白かったり.
勉強になった事もあり,思い出した事もあり,やっぱりプログラミングって楽しいよね!


LL実行速度の比較【方法】

それぞれの言語について,次の2通りの方法で,円周率πを求める計算を実行した.

今回は単に何らかの処理をさせたいだけなので,求める円周率のケタに興味はない.
なお,(1)は純粋に繰り返し計算を行う事にし,(2)は条件分岐や関数の利用等少し処理を増やす事にした.

また,実行するプラットフォームには,Mac OS XRed Hat Linuxを用いた.
対象の言語は,Perl, Ruby, Python, C, Java, Fortran(Linuxのみ).
それぞれのソースプログラムは,各言語の記述や文法の参考の為に,このエントリに付けておいた.*1

比較に用いたプログラムの実行時間は,プログラムを5回実行してその中央値を採用した..

LL実行速度の比較【結果】

それぞれのプログラムの結果は,次の通り.単位は全て秒.
実行時間でPerlに次ぐPythonは,Perlよりもやや遅い程度だけど,Rubyの遅さはちょっと目立つ.

プログラム1:ライプニッツの公式バージョンの実行時間
pi1 Mac OS X Red Hat Linux
Fortran - 7.535s
C 1.717s 7.587s
Java 2.007s 4.372s
Perl 27.886s 38.332s
Python 36.935s 40.587s
Ruby 70.308s 133.373s

プログラム2:モンテカルロ法バージョンの実行時間
pi2 Mac OS X Red Hat Linux
Fortran - 3.587s
C 2.184s 5.170s
Java 4.642s 13.766s
Perl 61.714s 71.661s
Python 76.739s 111.813s
Ruby 121.372s 234.658s

LL実行速度の比較【ソースプログラムープログラム1:ライプニッツの公式バージョン】

Perl(pi1.pl)
#!/usr/bin/perl

$max = 100000000;
$a = 0.0;

foreach( 0..$max ) {
  $a += (-1.0)**$_ / ( 2.0*$_ + 1.0 );
}

print "pi=". 4.0*$a ."\n";
Ruby(pi1.rb)
#!/usr/bin/ruby

max = 100000000
a = 0.0

for n in 0..max
  a += (-1.0)**n / ( 2.0*n + 1.0 )
end

print( "pi=", 4.0*a, "\n")
Python(pi1.py)
#!/usr/bin/python

max = 100000000
a = 0.0

for n in range( 0, max ):
  a += (-1.0)**n / ( 2.0*n + 1.0 )

print "pi=", 4.0*a
C(pi1.c)
#include<stdio.h>
#include<math.h>

int main(){
  int max = 100000000;
  int i;
  double a = 0.0;

  for( i = 0 ; i <= max ; i++ ){
    a = a + pow( -1.0, i ) / ( 2.0*(double)i + 1.0 );
  }

  printf( "pi=%.15f\n", 4.0*a );

  return 0;
}
Java(pi1.java)
class pi1{
  static public void main( String args[] ){
    int max = 100000000;
    int i;
    double a = 0.0;

    for( i =0 ; i <= max ; i++ ){
      a = a + Math.pow( -1.0, i ) / ( 2.0*(double)i + 1.0 );
    }

    System.out.println( "pi="+ 4.0*a );
  }
}
Fortran(pi1.f90)
program pi1
  implicit none
  integer :: max = 100000000
  integer :: i
  real(8) :: a = 0.0

  do i = 0, max
    a = a + (-1.0)**dble(i) / ( 2.0*dble(i) + 1.0 )
  end do

  print *, "pi=", 4.0*a
end program

LL実行速度の比較【ソースプログラムープログラム2:モンテカルロ法バージョン】

Perl(pi2.pl)
#!/usr/bin/perl

$max = 100000000;
$n = 0;

foreach( 0..$max ) {
  $n++ if ( &p() < 1.0 );
}

print "pi=". 4.0*$n / $max ."\n";

sub p{
  $x = rand();
  $y = rand();
  $r = sqrt( $x**2 + $y**2 );
  return $r;
}
Ruby(pi2.rb)
#!/usr/bin/ruby

def p
  x = rand
  y = rand
  r = Math.sqrt( x**2 + y**2 )
  return r
end

max = 100000000
n = 0

max.times{
  n += 1  if p < 1.0
}

print( "pi=", 4.0*n / max, "\n" )
Python(pi2.py)
#!/usr/bin/python
import math, random

def p():
  x = random.random()
  y = random.random()
  r = math.sqrt( x**2 + y**2 )
  return r

max = 100000000
n = 0

for i in range( 0, max ):
  if p()<1.0:
    n+=1

print "pi=", 4.0*n / max
C(pi2.c)
#include<stdio.h>
#include<math.h>
#include<stdlib.h>

int main(){
  int max = 100000000;
  int n = 0;
  int i;
  double p();

  for( i = 0 ; i <= max ; i++ ){
    if ( p() < 1.0 ) {
      n++;
    }
  }

  printf( "pi=%.15f\n", 4.0 * (double)n / (double)max );

  return 0;
}

double p(){
    double x, y, r;
    x = (double)rand() / (double)RAND_MAX;
    y = (double)rand() / (double)RAND_MAX;
    r = sqrt( pow( x, 2 ) + pow( y, 2 ) );
    return r;
}
Java(pi2.java)
class pi2{
  static public void main( String args[] ){
    int max = 100000000;
    int n = 0;
    int i;

    for( i = 0 ; i <= max ; i++ ){
      if ( p() < 1.0 ) {
        n++;
      }
    }

    System.out.println( "pi="+ 4.0 * (double)n / (double)max );
  }

  static double p(){
    double x, y, r;
    x = Math.random();
    y = Math.random();
    r = Math.sqrt( Math.pow( x, 2 ) + Math.pow( y, 2 ) );
    return r;
  }
}
Fortran(pi2.f90)
program pi2
  implicit none
  integer :: max = 100000000
  integer :: n = 0
  integer :: i
  real :: p

  do i = 0, max
    if ( p() < 1.0 ) then
      n = n + 1
    end if
  end do

  print *, "pi=", 4.0 * dble(n) / dble(max)
end program

function p()
  implicit none
  real :: x, y, p

  call random_number( x )
  call random_number( y )
  p = sqrt( x**2 + y**2 )

end function

*1:これは,僕自身が今後一番参照したりしてw