DNA Cafe | Download | FreeSoftware | Java | Links
ある日、友人 O からこんなメールがきた。
ね〜、これ ↓ ってホントなのかな?
http://www.ibm.com/jp/developerworks/java/051104/j_j-jtp09275.shtml
手元の環境で new Byte[1024] と new char(1024) を比べてみたのだけど、ヒープが穴だらけにならない限り、C++ の方が数倍速いのですが...
# ヒープを穴だらけにするパターンはまだ試してないので不明。
パフォーマンスは、実際に使う環境と同じ条件で計測しないと意味がない。 だからこの手の計測をしたことはあまりない。
でもね、ふつう Java と C++ の両方で本物のアプリケーションを作って動かすなんて、できない。
そこで、友人が計測した速さと実際のアプリケーションとの差がどこからくるのか、 ちょっと調べてみようと考えた。 どんな振る舞いをするのかがわかればどちらを使うか決めるのに役にたつし、ね。
と、ゆーわけで、実際にベンチマークを作って計測してみることにした。
サイズ len のメモリを確保するオブジェクトを単純に N 回作るテストプログラムを C, C++, Java のそれぞれについて作成した。
ベンチマークのソースファイル一式 → malloc_test.tar.bz2 (2643 bytes)
C | GCC 3.4.4 gcc | -g -O0 |
---|---|---|
C++ | GCC 3.4.4 g++ | -g -O0 |
GCJ | GCC 3.4.4 gcj | -g -O0 |
Java | Sun JDK 1.5.0_05 | デフォルトで動作 |
ハードウエアは ThinkPad i1620 2661-23J (M-Celeron 500MHz LV, 320MB) で OS は Linux 2.6.14 + GNU libc 2.3.6 (NPTL を使用)である。 計測には GNU time 1.7 を使い、 コマンド実行のユーザー時間とシステム時間を計測した。 なお、計測値の誤差は測定していないが、複数回試行して傾向が再現することを確認している。
結果を図にしたものを以下に示す。縦軸は実行時間(秒)、横軸は確保メモリ数(バイト)である。
Fig. 1: 1-256k * 100000 times, user time
Fig. 2: 1-256k * 100000 times, sys time
Fig. 3: 8k-1M * 10000 times, user time
Fig. 4: 8k-1M * 10000 times, sys time
Fig. 5: 256k-64M * 1000 times, user time
Fig. 6: 256k-64M * 1000 times, sys time
ハードウエアや OS で結果が変わるだろう、ということをふまえた上で、
多くのアプリケーションでは、小さなオブジェクトが大きなものより多く作られる。 単純に考えると C++ が有利となるはずだが、 Java だと動的にメモリ最適化(例えばメモリコンパクション)ができる利点があり、 これが有効に働く可能性がある。
ベンチマークの結果から見ると Java や GCJ の GC はかなり優秀で、確保メモリが大きい場合には実時間で C++ と変わらない。 これは、小さなオブジェクトが多い場合でもメモリ最適化が有効に働くと、 実時間で同等になることを意味する。
メモリ管理は OS やライブラリに に組み込まれている機能が多くあり、単純には比較できないが、 Java アプリケーションの性質が GC を有効に利用できるものか、ということが性能に大きくかかわるだろう。
もう少し詳しいベンチマークの結果が shuJIT で知られる首藤さんのページにある。 これを見るとほんとに C++ と Java ってたいして差がないって感じる。