2009年4月15日水曜日

Apache22 Perl Ruby PHP python Javaの速度比較 ベンチマーク

AMD GeodeNX1500/1050MHz
ASRock K7VT4A PRO
------------------------------
FreeBSD7.1/i386
Apache2.2.11
PHP5.2.9
Ruby1.8.7
Ruby1.9.1
Perl5.8.9
Python2.5.4
Java(JDK1.6.0)
GCC4.2.1
------------------------------
Apache上で動作させたスクリプトは実際のところどのスクリプトが早く、
速度差はどのくらいなのでしょうか?
ネットで検索してみても古い記事しかみつからず、PHP(PHP3)がもっとも遅い
といった結果しか見つけられませんでした。
しかしながら、PHPも今ではPHP5にバージョンアップされ、Zend社のランタイムコンパイラが内蔵されたことから、もっと高速化されているはずです。

簡単な例ながらベンチマークテストを行った結果次のようになりました。

1から100万までの総和の計算
C++0.0083sec (参考値)
PHP5.20.53sec
Java1.60.59sec
Perl5.81.38sec
Ruby1.91.49sec
Python2.51.59sec
Ruby1.82.69sec


C++は置いといて、この結果からするとPHP5.2がもっとも高速でした。
Ruby1.9が最も高速だと思っていましたが、Perlよりも遅いという結果でした。

さて、この結果はApacheへの1リクエストについての時間相当になるのですが、実際Apache上から呼び出されたときには、そのスクリプトが実行されるまでのオーバーヘッドとスクリプトの終了処理が発生するわけで、小さなトランザクションが多量に発生した場合の実行速度とはまったく別の結果が出るはずです。

この点についてはまた後ほど評価いたします。


次のコードでテストを行いました。
条件をなるべくそろえるために、同じようなコードになるようにしています。

PHP
[bench.php]

<?
$time_start = microtime(TRUE);

$sum = 0;

for($i = 0;$i <= 1000000;$i ++)
{
$sum = $sum + $i;
}
echo "Result:$sum<br>\n";

$time_end = microtime(TRUE);
$time_use = $time_end - $time_start;

echo "Start:$time_start<br>\n";
echo "End:$time_end<br>\n";
echo "Use:$time_use<br>\n";

?>


Perl
[bench.pl]

#!/usr/local/bin/perl
##
## bench.pl
##
use Time::HiRes;


print "Content-type: text/plain; charset=iso-8859-1\n\n";

$usecStart = Time::HiRes::gettimeofday();

$i = 0;

for($i = 0;$i <= 1000000;$i ++){
$sum = $sum + $i;
}

$usecEnd = Time::HiRes::gettimeofday();
$usecUse = $usecEnd - $usecStart;

print "Result:${sum}<br>\n";
print "Time:${usecUse}<br>\n";


Ruby
[bench.rb]

#!/usr/local/bin/ruby

print "Content-Type: text/html\n"
print "\n"

tmStart = Time.now

sum = 0
i = 1
while i <= 1000000
sum = sum + i
i = i + 1
end

tmEnd = Time.now

print "Result:#{sum}<br>\n"

tm = tmEnd - tmStart

fTime = tm.to_f
print "Sec:#{fTime}"



Python
[bench.py]

#!/usr/local/bin/python
##
## bench.py
##
import time

print "Content-type: text/plain; charset=iso-8859-1\n\n"

print "Hello World"

msecStart = time.time()


sum = 0
i = 0

while i <= 1000000:
    sum = sum + i
    i = i + 1

msecEnd = time.time()

print "Start:" , msecStart
print "End:" , msecEnd

msecUse = msecEnd - msecStart

print "Time:" , msecUse



Java (JDK1.6.0 diablo-caffe)

class Bench{
public static void main(String args[]){

long lStart,lEnd,lUse;

lStart = System.currentTimeMillis();

long lCount,lSum;
lSum = 0;
for(lCount = 0;lCount <= 1000000;lCount ++)
{
lSum = lSum + lCount;
}

lEnd = System.currentTimeMillis();

System.out.print("Result:");
System.out.println(lSum);

lUse = lEnd - lStart;

System.out.print("Time:");
System.out.println(lUse);



}
}



C++ (GCC4.2.1)
[bench.cpp]

#include <stdio.h>
#include <string.h>
#include <time.h>

int main()
{
timespec tsStart,tsEnd,tsUse;

memset(&tsStart,0,sizeof(timespec));
memset(&tsEnd,0,sizeof(timespec));
memset(&tsUse,0,sizeof(timespec));


clock_gettime(CLOCK_REALTIME,&tsStart);

int i = 0,sum = 0;

for(i = 0;i <= 100000000;i ++)
{
sum = sum + i;
}

clock_gettime(CLOCK_REALTIME,&tsEnd);

double dStart,dEnd,dUse;

dStart = (double)tsStart.tv_sec + (double)tsStart.tv_nsec * 0.000000001;
dEnd = (double)tsEnd.tv_sec + (double)tsEnd.tv_nsec * 0.000000001;
dUse = dEnd - dStart;

printf("Start:%f\n",dStart);
printf("End:%f\n",dEnd);
printf("Use:%7.2f\n",dUse);
}
----------------

#g++ bench.cpp
#./a.out

C++は概算です。

.

0 件のコメント: