実行時最適化を行わないJavaの遅さは、驚異的なものだった。
では何故、そんなにも遅いのだろうか。
もう一度、Javaが遅い理由として挙げられているものを振り返ってみよう。
- 実行時のエラーチェックの厳密さ
- VM(バーチャルマシン)という仕組み
- 最適化の不十分さ
- 言語仕様上の問題
- ガベージコレクタの影響
※上記には、esper氏の指摘(GCの影響)も追加しました。有難うございます。
これらを検証するために、Javaの実行Profileを見てみよう。
Profileを取得するには、以下のようにしてJavaを実行すればよい。
java -Xprof -Xint Test >prof.txt
今回は最適化をせずに実行するので、「-Xint」オプションも同時に指定している。
結果は、以下である。
Flat profile of 153.22 secs (9788 total ticks): main Interpreted + native Method 70.8% 6790 + 140 sun.io.CharToByteDoubleByte.convert 5.9% 581 + 0 sun.io.CharToByteMS932.convSingleByte 4.1% 400 + 3 sun.nio.cs.StreamEncoder$ConverterSE.implWrite 3.3% 182 + 142 sun.nio.cs.StreamEncoder.write 2.8% 277 + 0 sun.nio.cs.StreamEncoder.write 2.5% 243 + 1 sun.io.CharToByteConverter.convertAny 2.4% 237 + 0 java.lang.String.getChars 1.7% 164 + 0 java.io.PrintWriter.write 0.9% 16 + 76 java.lang.System.arraycopy 0.9% 92 + 0 Test.main 0.9% 87 + 0 java.io.PrintWriter.write 0.8% 75 + 0 java.io.PrintWriter.print 0.4% 40 + 0 sun.nio.cs.StreamEncoder.ensureOpen 0.3% 33 + 0 java.io.PrintWriter.ensureOpen 0.3% 0 + 30 java.io.FileOutputStream.writeBytes 0.3% 29 + 0 java.io.OutputStreamWriter.write 0.2% 23 + 0 sun.io.CharToByteConverter.nextByteIndex 0.2% 21 + 0 java.lang.String.length 0.1% 0 + 9 java.lang.Throwable.fillInStackTrace 0.0% 0 + 1 java.nio.charset.Charset$1.0.0% 1 + 0 java.io.FileOutputStream.write 0.0% 1 + 0 java.lang.ref.SoftReference.get 0.0% 1 + 0 java.io.ByteArrayInputStream.read 99.1% 9293 + 402 Total interpreted Thread-local ticks: 0.0% 1 Blocked (of total) 0.0% 1 Class loader 0.6% 59 Interpreter 0.3% 27 Unknown: running frame 0.1% 5 Unknown: thread_state Global summary of 153.22 seconds: 100.0% 9807 Received ticks 0.1% 10 Received GC ticks 0.1% 7 Other VM operations 0.0% 1 Class loader 0.6% 59 Interpreter 0.3% 32 Unknown code
これを見て分かることは、sun.io.CharToByteDoubleByte.convertの処理にほとんど(70%)の時間を費やしているということである。
「Received GC ticks」の処理全体に占める割合が僅か0.1%であることから、この処理の場合にはGCの影響を無視して良さそうだ。
(もちろん、GCの影響の大きな処理も存在するだろう。それは別途検証する必要がある)
エラーチェックについては、このリストを見るだけでは良く分からない。どなたか分かる方に解説をお願いしたいところだ。
結局、この実行速度の遅さはJavaVM上で動いているということに大きく依存しているのではないだろうか。
次は、実行時最適化の際のProfileと比較して、それを検証してみたい。