『プログラミング言語人気TOP10の簡易解説』という記事が人気を呼んでいたのだが、軽快な語り口で面白い読み物だが、語弊がありそうな部分がある。その中で特に、「(Javaは)実行速度はCに及ばないもののスクリプト言語よりは数十倍速い」とある部分が気になったので、簡単な例で検証してみた。
1. Python、PHP、Java、Cで不適切な速度比較を行う
最初にコーディングが不適切な場合にプログラミング言語の速度比較を行うと、通説と異なる結果になる事を示したい。
Ubuntu Linuxで、オブジェクトをなるべく使わずに、順列の整数を100万個生成し、ランダムにシャッフルし、クイックソートを行ったときの経過時間を、timeコマンドで計測したものだ。ソート前、ソート後に配列の内容を、", "で連結して標準出力に書き出している。また、PythonはAPIをなるべく使ったもの(*無し)と、なるべく使わなかったもの(*有り)で計測した。CPythonを用いている。
Python 2.6.5 |
Python* 2.6.5 |
PHP 5.3.2 |
Java 1.6.0_22 |
gcc 4.4.3 |
|
---|---|---|---|---|---|
real | 2.469s | 12.259s | 3.956s | 5.959s | 0.531s |
user | 2.368s | 12.165s | 3.660s | 3.532s | 0.492s |
sys | 0.100s | 0.080s | 0.284s | 2.424s | 0.040s |
ベンチマーク結果は、C、Python、PHP、Java、Python*の順番で速い。つまり、PythonやPHPが、Javaより速度が速くなっている。また、APIを使わないでスクリプトでクイック・ソートやシャッフルを実装した場合は、APIを使った場合より5倍弱遅い。適切なAPIを利用していくことが、スクリプト言語を使うコツになるのは確かなようだ。
2. Javaがスクリプト言語より遅くなった理由
オーバーヘッドの箇所は明確で、100万回もプリミティブ型を文字列オブジェクトに変換し、出力しているので、オブジェクト(インスタンス)の生成に時間がかかっている。これを文字列連結用のAPIを使い、インスタンス生成の回数を抑えると、下表のように劇的に速くなる。
工夫無し | 工夫有り | 削減幅 | |
---|---|---|---|
real | 5.959s | 0.854s | -85.7% |
user | 3.532s | 0.672s | -81.0% |
sys | 2.424s | 0.180s | -92.6% |
100万回のSystem.out.println()の呼び出しを、StringBuilderを使い1回にしただけだが、85%以上の時間を削減する事ができている。逆に言うと、Javaは油断すると遅いコードになりやすい。
3. C、Java、Python、Perl、PHP、Rubyで300万件のソートにかかる時間を比較する
せっかくなので、人気のスクリプト言語Python、Perl 5.10.1、PHP、Ruby 1.8.7の速度差を評価してみる。ベンチマークとして、C、C++とJavaを併記している。CとJavaは書き方によって速度が大きく変化するが、Javaは上述の工夫と、Cはitoa関数の高速化版を用いた。C++はテンプレート・クラスvectorとrandom_shuffleを用いてC++らしくし、あえてCとの差をつけている。
real | user | sys | C言語比 | |
---|---|---|---|---|
C | 1.478 | 1.432 | 0.040 | 1.0 |
C++ | 1.806 | 1.736 | 0.068 | 1.2 |
Java | 2.629 | 2.168 | 0.408 | 1.5 |
Python | 7.999 | 7.832 | 0.160 | 5.5 |
Perl | 10.339 | 9.673 | 0.648 | 6.8 |
PHP | 13.777 | 12.849 | 0.868 | 9.0 |
Ruby | 24.193 | 22.357 | 1.788 | 15.6 |
JRuby | 15.543 | 13.677 | 1.936 | 9.6 |
結果はCとC++が傑出しており、次にJava、だいぶ離されてPython、Perl、PHP、最後尾にRubyがつく形となっている。RubyはJRuby 1.6.0RC1よりも遅く、最新版の1.9.2 p136でも大きな速度の改善は見られなかった。なお今回のベンチマークで利用したプロセッサはAMD Phenom IIで、Intel系のプロセッサを用いた場合、異なる結果が出る可能性がある。
追記(2011/2/3):Cのソースコードに問題が発見されたので、結果に訂正を入れた。また、CとC++の速度差だが、純粋なソート時間ではCが0.518秒、C++が0.237秒程度となっており、テンプレート・ライブラリの高速性が否定されたわけでは無い。
4. プログラム言語の速い・遅いは難しい
上述のベンチマークからは、C > Java > スクリプト言語の処理速度となり、Javaとスクリプト言語の速度差も4~10倍程度で、概ね通説と一致する結果となった。しかし、ちょっとした前提条件でJavaとスクリプト言語の処理速度の差が逆転することも事実だ。また、複雑な演算があるコードならJavaの方が速くなると考えられるが、文字列処理とデータベースとのやり取りが主な場合は、何十倍の速度差はつかないと思われる。
近年はソフトウェアの速度に対する要求は年々低くなってきているので、稼働環境や職場の事情などが許すならば、プログラマが快適に書ける言語を選択するべきであろう。嫌いな言語で不適切なコードを書くよりも、好きな言語で適切なコードを書く方が、結局は速度的にも有利なことが多いからだ。お気に入りのプログラミング言語を使いこなす事を心がけた方が、実行速度が出る慣れない言語に頼るよりも、より良いソフトウェアを作れる事が多いように感じる。
0 コメント:
コメントを投稿