Crystalはどれくらい速いのか
Ruby風の文法で、ネイティブコンパイルできる言語『Crystal』。
実際に使ってみましたが、凄そうな予感がします。そこで、実際にパフォーマンスを計測することにしました。実行環境は以下の通りです。
- PC: MacBook Air Late 2010
- OS: Mac OS X 10.9.5
- CPU: 1.6 GHz Intel Core 2 Duo
- メモリ: 4GB 1067 MHz DDR3
測定方法は竹内関数で、コードは後記します。
測定する言語
補足
コンパイラのバージョン
$ gcc -v Configured with: --prefix=/Applications/Xcode.app/Contents/Developer//usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn) Target: x86_64-apple-darwin13.4.0 Thread model: posix $ g++ -v Configured with: --prefix=/Applications/Xcode.app/Contents/Developer//usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn) Target: x86_64-apple-darwin13.4.0 Thread model: posix $ crystal -v Crystal 0.7.6 [eb13f75] (Thu Aug 13 22:00:15 UTC 2015) $ java -version Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8 java version "1.8.0_05" Java(TM) SE Runtime Environment (build 1.8.0_05-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode) $ ruby -v ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin13]
測定結果
たらい回し関数の実行時間を示しています。短い方がパフォーマンスが良いということです。
CrystalとRubyの実行速度の違いは歴然ですね。CrystalはCと同等の速さを示しています。JavaとCrystalが妙に速いのは、末尾再帰最適化とGCのためだと思われます。
コード
C
#include <stdio.h> #ifdef WIN32 #include <windows.h> double get_time() { LARGE_INTEGER t, f; QueryPerformanceCounter(&t); QueryPerformanceFrequency(&f); return (double)t.QuadPart/(double)f.QuadPart; } #else #include <sys/time.h> #include <sys/resource.h> double get_time() { struct timeval t; struct timezone tzp; gettimeofday(&t, &tzp); return t.tv_sec + t.tv_usec*1e-6; } #endif // ========================== int tarai(int x,int y,int z){ if(x <= y){ return y; }else{ return tarai(tarai(x-1,y,z), tarai(y-1,z,x), tarai(z-1,x,y)); } } int main() { double t1 = get_time(); int n = tarai(14,8,0); double t2 = get_time(); printf("%d\n", n); printf("%f ms\n", (t2 - t1) * 1000.0); }
C++
#include <iostream> #ifdef WIN32 #include <windows.h> double get_time() { LARGE_INTEGER t, f; QueryPerformanceCounter(&t); QueryPerformanceFrequency(&f); return (double)t.QuadPart/(double)f.QuadPart; } #else #include <sys/time.h> #include <sys/resource.h> double get_time() { struct timeval t; struct timezone tzp; gettimeofday(&t, &tzp); return t.tv_sec + t.tv_usec*1e-6; } #endif // ========================== int tarai(int x,int y,int z){ if(x <= y){ return y; }else{ return tarai(tarai(x-1,y,z), tarai(y-1,z,x), tarai(z-1,x,y)); } } int main() { double t1 = get_time(); int n = tarai(14,8,0); double t2 = get_time(); std::cout << n << std::endl; std::cout << (t2 - t1) * 1000.0 << " ms" << std::endl; }
Crystal, Ruby
def tarai(x,y,z) if x <= y y else tarai(tarai(x-1,y,z), tarai(y-1,z,x), tarai(z-1,x,y)) end end t1 = Time.now n = tarai(14,8,0) t2 = Time.now puts n puts t2 - t1
Java
public class Tak { public static int tarai(int x,int y,int z){ if(x <= y){ return y; }else{ return tarai(tarai(x-1,y,z), tarai(y-1,z,x), tarai(z-1,x,y)); } } public static void main(String[] args) { long t1 = System.currentTimeMillis(); int n = tarai(14,8,0); long t2 = System.currentTimeMillis(); System.out.println(n); System.out.println((t2 - t1) + " ms"); } }