2012-02-17 16 views
0

私は説明できない1つの問題があります。必要であればJavaでのメソッドの実際の実行時間はどのくらいですか、それはどのように依存しますか?

String numberStr = "3151312423412354315"; 

System.out.println(numberStr + "\n"); 
System.out.println("Lehman method: "); 
long beginTime = System.currentTimeMillis(); 
System.out.println(Lehman.getFullFactorization(numberStr)); 
long finishTime = System.currentTimeMillis(); 
System.out.println((finishTime-beginTime)/1000. + " sec."); 

System.out.println(); 

System.out.println("Lehman method: "); 
beginTime = System.currentTimeMillis(); 
System.out.println(Lehman.getFullFactorization(numberStr)); 
finishTime = System.currentTimeMillis(); 
System.out.println((finishTime-beginTime)/1000. + " sec."); 

:ここでの主な関数のコードは、文字列形式の素因数のArrayListを返すLehman.getFullFactorization(...)方法。ここで

が出力されます。

3151312423412354315 

Lehman method: 
[5, 67, 24473, 384378815693] 
0.149 sec. 

Lehman method: 
[5, 67, 24473, 384378815693] 
0.016 sec. 

私はそれを見たとき、私は、驚きました。同じメソッドの2回目の実行が最初のものよりもずっと早いのはなぜですか?最初に、メソッドの最初の実行時に、JVMとそのリソースを実行する時間を計算することは考えましたが、不可能です.JVMが「メイン」メソッドの実行前に開始することは明らかです。

+0

その同じ?つまり、秒はいつもより速いのですか? – sgowd

+0

アレクサンダーは、ので、すべてのユーザーがそれを読むことができ、あなたの名前を変更してください。誰もがキリル文字を読むことはできません;) –

答えて

1

はそれを超える1万回をやってみて、それははるかに速くなります。これは、コードが最初にロードする必要があるため(高価な)その後、インタプリタモード(OKスピード)で実行され、最終的には(ずっと速く)

あなたはこれを試すことができますネイティブコードにコンパイルされているのですか?常に

int runs = 100*1000; 
for(int i = -20000 /* warmup */; i < runs; i++) { 
    if(i == 0) 
     beginTime = System.nanoTime(); 
    Lehman.getFullFactorization(numberStr); 
} 
finishTime = System.nanoTime(); 
System.out.println("Average time was " + (finishTime-beginTime)/1e9/runs. + " sec."); 
0

JVMが最初の計算の結果をキャッシュしているとします。 JITは行動している。

2

JavaのJITコンパイラ(​​参照)は、メソッドの最初の実行を開始し、そのメソッドのコードの最適化を実行することがあります。これは、その後のすべての実行を高速化することになっています。私はこれがあなたの場合に起こるかもしれないと思う。

0

2つ目の実行を高速化する2つのことがあります。

  1. 初めてメソッドを含むクラスを読み込む必要があります。二度目は、既に記憶に残っています。
  2. 最も重要なことに、JITは実行されることの多いコードを最適化します。最初の呼び出しでは、JVMはバイトコードを解釈して起動し、マシンコードにコンパイルして実行を続行します。 2回目は、コードはすでにコンパイルされています。

Javaのマイクロベンチマークは、検証が難しいことがよくあります。

0

私の推測では、最適化のためにCPU上のL1/L2キャッシュに保存されていると思います。

Javaはもう一度それを解釈する必要はなく、すでにコンパイルされたコードとしてメモリから呼び出すことができます。

関連する問題