Java V.S. C++

昨日の実験結果がちょっと納得いかなかったので,
Java VM V.S. ネイティブコード - なぜか数学者にはワイン好きが多い
単純にループ回数を10倍にしてみました.

> gcj42 -C Pendulum.java S-Euler.java ; jar42 cvfm Pendulum.jar META-INF/MANIFEST.MF *.class
  adding: Pendulum.class        (in=983) (out=607) (deflated 38%)
  adding: S_Euler.class (in=555) (out=349) (deflated 37%)
  adding: META-INF/     (in=0) (out=0) (stored 0%)
  adding: META-INF/MANIFEST.MF  (in=70) (out=68) (deflated 3%)
total bytes=1608, compressed=1024 -> 36% savings
> time java -jar Pendulum.jar Pendulum
1.0,0.01
-0.926466004711948,-0.38103929142888787
0.7201228813478374,0.6974565073580707
-0.41054996704368263,-0.9138931625952093
0.04212461468187757,0.9993230097447542
0.33233931148399837,-0.9414996593503935
-0.6591623161707432,0.7487121028153431
0.8914942418259135,-0.44859648345965675
-0.996030250157117,0.08417444862477214
0.9577850788353137,0.2923140139811242
time=4969
5.111u 0.294s 0:06.77 79.7%     93+1127k 137+6io 83pf+0w
> gcj42 -o pendulum.out --main=Pendulum Pendulum.java S-Euler.java ; time ./pendulum.out
1.0,0.01
-0.926466004711948,-0.38103929142888787
0.7201228813478374,0.6974565073580707
-0.41054996704368263,-0.9138931625952093
0.04212461468187757,0.9993230097447542
0.33233931148399837,-0.9414996593503935
-0.6591623161707432,0.7487121028153431
0.8914942418259135,-0.44859648345965675
-0.996030250157117,0.08417444862477214
0.9577850788353137,0.2923140139811242
time=9807
9.879u 0.031s 0:10.65 92.9%     10+1858k 0+0io 171pf+0w

Javaの方が2倍速い...
これじゃ,下手したらg++よりもJavaの方が速いんじゃないか?!
と思って,プログラムをC++用に書き換えてみました.そっくりですが,基底クラスはこんな感じです.

class S_Euler
{
public:
  double tau,p,q;
  S_Euler(double t, double p0, double q0)
  {
    tau = t;
    p = p0;
    q = q0;
  }
  virtual double f(double p, double q) = 0;
  virtual double g(double p, double q) = 0;
  void step()
  {
    p = p - tau*f(p,q);
    q = q + tau*g(p,q);
  }
  double get_p()
  {
    return(p);
  }
  double get_q()
  {
    return(q);
  }
};

これをスーパークラスにしたサブクラスは,こんな感じです.

#include <iostream>
#include <time.h>
#include "S-Euler.cc"
using namespace std;
class Pendulum : public S_Euler
{
public:
  Pendulum(double t, double p, double q):S_Euler(t,p,q)
  {
  }
  double f(double p,double q)
  {
    return(q);
  }
  double g(double p,double q)
  {
    return(p);
  }
};
int main(int argc, char *argv[])
{
  Pendulum a(0.01,1,0);
  clock_t start = clock();
  for(int i=0;i<100000000;++i)
  {
    a.step();
    if(i%10000000==0)
    {
      cout<<a.p<<","<<a.q<<endl;
    }
  }
  cout<<"time="<<((double)clock()-start)/CLOCKS_PER_SEC*1000.0<<endl;
  return(0);
}

コンパイルして実行してみます.

> c++ -o pendulum.out Pendulum.cc ; time ./pendulum.out
1,0.01
-0.926466,-0.381039
0.720123,0.697457
-0.41055,-0.913893
0.0421246,0.999323
0.332339,-0.9415
-0.659162,0.748712
0.891494,-0.448596
-0.99603,0.0841744
0.957785,0.292314
time=6414.06
6.420u 0.007s 0:06.47 99.2%     5+1101k 0+0io 0pf+0w

...Javaの方が速いです.
c++バージョンはこんな感じです.

> c++ -v
Using built-in specs.
Target: i386-undermydesk-freebsd
Configured with: FreeBSD/i386 system compiler
Thread model: posix
gcc version 4.2.1 20070719  [FreeBSD]