• 検索結果がありません。

Java における時間測定について

ドキュメント内 i I Java Java Java (ページ 130-133)

第 2 章 Java 言語の基本的な文法 I 5

2.20 応用プログラム ( 配列の要素のソーティング )

2.20.8 Java における時間測定について

ここまで、いろいろなソーティングアルゴリズムを紹介し、それらを同じデータに対する経過時間で比較してみまし たが、果たしてこの実験結果はどれほどの信頼性があるのでしょうか。また、果たして、この経過時間は正確なので しょうか。

まず、Javaにおいて測定できる時間には、次の2種類があります。

• System.currentTimeMillis():ミリ秒単位での測定(1 msec = 103 sec)

• System.nanoTime():ナノ秒単位での測定(1 nsec = 109 sec)

currentTimeMillis()が現在の時刻に関連したミリ秒単位の値を返すのに対し、nanoTime()は時刻とは無関係な 時間測定のためのナノ秒単位の値を返します。但し、APIドキュメントを読んでみると、必ずしも解像度がナノ秒で あるという保証は無いとあります。とりあえず、プログラムの計測を行うのにミリ秒単位は利用価値が無いでしょうか ら、ナノ秒での測定について見ていきましょう。なお、こうしたプログラムの性能評価のことを、「ベンチマークテス ト」と言います。

ソースコード2.105 TimePrecisionExample.java (時間測定)

package section0220;

public class TimePrecisionExample {

public static void main(String[] args) { final int N = 1000000;

int count = 50;

int x = 0;

for(int k=0; k<count; k++) {

long startTime = System.nanoTime();

for(int i=0; i<N; i++) { x++;

}

long endTime = System.nanoTime();

System.out.printf( "%d nsec%n", (endTime - startTime) );

}

System.out.println( "x = " + x );

} }

上記のプログラムを以下の2種類のマシーンで実行した結果が表2.20.1 です。なお、こうした測定を行う場合は、他 の要因が少しでも少なくなるように、他のアプリを停止したり、ネットから切断して実行しましょう。

• Windows 10 Pro / Intel Core i5-3337U 1.80GHz

• MacOS X 10.11.6/ Intel Core i7 2.20GHzz

結果から読み取れることは何でしょうか?まず、実験自体は毎回同じ処理(変数xに1 をN 回加える繰り返し)を しているはずです。従って、理論上は毎回同じ測定時間になるはずですね。しかし、いずれの場合も、最初の数回は 極端に時間がかかっています。これは、Java がプログラムを開始するに際し、何らかの追加的な仕事を処理とは別に 行っているということですね。Javaは中間言語に翻訳されたclassファイルをインタプリタがJVM内で実行します。

そのとき、クラスの設定、フィールド(変数)の確保等々、最初にいろいろな仕事をしなければいけません。それをや りながらプログラムは実行をしているので、初期の処理は本来の実行速度が測れないのです。

その後、いずれのパソコンでも安定して同じような処理時間(Windowsが0、Macが38)が続きます。処理をやっ ているのですから、0 nsecということはありえませんから、パソコンのタイマーが進む以前に終わってしまったという ことですね。では、WindowsがMacOSより圧倒的に早いのでしょうか?いえ、Windowsの値を見ると、時々 570 くらいの数値が顔を出します。つまり、タイマーは 0 nsecの次(?) に大きな値として570 nsecを測定できるけれど、

その間の値は測定できないのでは(?) と考えられます。同様にMacOSの場合も、似通った値が飛び飛びに現れてい ます。

k 0 1 2 3 4 5 6 7 8 9 10 11

Windows 7842292 6009725 2638235 570 0 6676269 2779070 0 0 0 0 0

MacOS X 2251628 4580460 125 38 38 38 39 38 38 39 38 38

k 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

Windows 0 0 0 0 571 0 0 0 570 0 0 0 0 0 0 0 0

MacOS X 38 38 38 38 39 38 38 38 38 26 72 38 39 38 38 38 38

表2.20.1 Javaによる時間測定

表2.20.2では、繰り返し回数N を変えて測定してみました。何と、N を増やすと測定時間0 が現れます。このこ

とは、繰り返し回数を増やすと、何らかの最適化が行われて、実際は繰り返しを行わないという結果になっていると考 えられます。Javaのコンパイラは、単純作業に対して最適化を行うので、それが時間測定の難しさにもなっています。

Java のベンチマークテストについての詳細な説明が、以下のページで解説されていますので、参考にしてみて下さ い。>「確実なJavaベンチマーク」(https://www.ibm.com/developerworks/jp/java/library/j-benchmark1.html)

n 0 1 2 3 4 5 6 7 8

10 1710 570 0 570 570 570 570 570 0

100 1710 1711 1141 1140 2281 1141 1140 1141 1141

1000 15395 14825 11973 11404 11974 11403 11404 11404 11404

10000 119169 116887 115747 116317 135703 116888 124870 115747 115177

100000 1732785 330135 283951 278249 608385 440181 441322 392286 466980

1000000 7842292 6009725 2638235 570 0 6676269 2779070 0 0

10000000 4146368 6632934 0 7951767 0 0 0 0 0

n 9 10 11 12 13 14 15 16 17 18

10 571 570 570 570 570 570 570 570 570 570

100 1140 5131 1140 2281 1711 1710 2281 1710 1140 1711

1000 11404 11404 10834 11404 13114 19957 19956 20526 19387 19956

10000 115176 115177 132283 49036 43334 46755 852993 46755 48465 41053

100000 433909 741237 80395 0 1579976 684790 436760 477243 476103 367197

1000000 0 0 0 0 0 0 0 571 0 0

10000000 0 570 0 0 570 0 0 0 0 0

表2.20.2 配列の長さを変えて時間測定(Windows)

ドキュメント内 i I Java Java Java (ページ 130-133)