Javaプログラムの実行速度を計る方法


85

Javaプログラムの実行時間をどのように計りますか?これを行うためにどのクラスを使用すべきかわかりません。

私はちょっと次のようなものを探しています:

// Some timer starts here
for (int i = 0; i < length; i++) {
  // Do something
}
// End timer here

System.out.println("Total execution time: " + totalExecutionTime);

回答:


139
final long startTime = System.currentTimeMillis();
for (int i = 0; i < length; i++) {
  // Do something
}
final long endTime = System.currentTimeMillis();

System.out.println("Total execution time: " + (endTime - startTime));

2
実際にはnanoTimeである必要があります
Eugene

6
nanoTimeであってはなりません。rhuの答えを参照してください。
fabspro 2013

4
ここで「ファイナル」を使用した特別な理由はありますか?そのキーワードを削除した場合はどうなりますか?
dijxtra 2013

9
@dijxtra usingにfinalは、誤って割り当てることができないという利点があります(また、匿名クラスアクセスなどの他の利点もあります)。このコードでは、違いはありません。すべてを作成しfinalfinal必要な場合にのみ統合することは、かなり一般的な方法です。
wchargin 2013

1
テストするコードは、時間測定とともに複数回実行する必要があり、最初の結果は破棄する必要があります。1つ目は、クラスの読み込み時間などが含まれる可能性があります。複数回実行することで、もちろん、より便利で信頼性の高い平均が得られます。
Arun Ramakrishnan 2016

34

System#nanoTime()マルチコアCPUで経過時間を記録するために確実に使用できない問題があることに注意してください...各コアは独自のTSC(タイムスタンプカウンター)を維持しています:このカウンターはナノ時間を取得するために使用されます(実際にはCPUが起動してからのティック数)。

したがって、OSがコアの同期を維持するためにTSCタイムワープを実行しない限り、最初の時刻の読み取りが行われたときにスレッドが1つのコアでスケジュールされ、別のコアに切り替えられると、相対時間が散発的に後方にジャンプするように見える可能性がありますと転送します。

私はこれをAMD / Solarisで少し前に観察しました。そこでは、2つのタイミングポイント間の経過時間が負の値または予想外に大きな正の数として戻ってくることがありました。AMD PowerNow!を強制するために必要なSolarisカーネルパッチとBIOS設定がありました。オフ、それはそれを解決したように見えた。

また、System#nanoTime()VirtualBox環境でJavaを使用する場合、これまでに修正されていないバグがあります(AFAIK)。java.util.concurrencyパッケージの多くがナノ時間に依存しているため、あらゆる種類の奇妙な断続的なスレッドの問題が発生します。

参照:

System.nanoTime()は完全に役に立たないのですか? http://vbox.innotek.de/pipermail/vbox-trac/2010-January/135631.html


9

現在のシステム時刻をミリ秒単位で取得します。

final long startTime = System.currentTimeMillis();

次に、これから行うことを実行します。

for (int i = 0; i < length; i++) {
  // Do something
}

次に、どのくらいの時間がかかったかがわかります。

final long elapsedTimeMillis = System.currentTimeMillis() - startTime;

BalusCの答えも正しいです。必要なタイマーの解像度と、タイミングが必要な理由によって異なります。
Jonathan Feinberg 2010

9

を利用できますSystem#nanoTime()。実行の前後にそれを取得し、計算を行うだけです。System#currentTimeMillis()精度が高いため、上記の方が適しています。使用するハードウェアとプラットフォームによっては、経過時間に誤ったギャップが生じる可能性があります。ここで、Windows上のCore2Duoでは、約0〜15ミリ秒の間、実際には何も計算できません。

より高度なツールはプロファイラーです。


Windowsのタイマーは、デフォルトでは特に優れた解像度を備えていません。そこ高性能タイマーはあまりにも、それははるかに困難だCからでも使用するとJavaは(私の知る限り)JNIなし牛車のレベルがサンクそのローへのアクセスを提供していません。
ドナーフェロー

1
nanoTime()1つの問題があります(少なくともWindowsでは)。タイムスタンプはプロセッサコアに固有です。あるコアで「開始」タイムスタンプを取得し、別のコアで「停止」タイムスタンプを取得したため、実行時間が負のプログラムがありました。
gustafc 2010

3

単純なものの場合、System.currentTimeMillis()が機能します。

実際には、IDEが「t0」と入力すると、次の行が生成されるように設定されていることがよくあります。

final long t0 = System.currentTimeMillis()

ただし、より複雑な場合は、次のような統計的な時間測定を使用することをお勧めします(少し下にスクロールして、標準偏差などを含めて表現された時間測定を確認します)。

http://perf4j.codehaus.org/devguide.html


自動生成コードを指摘するための+1。私はいつも同じようなステートメントを使用していて、コードテンプレートの挿入について知りませんでした。Eclipseでそれを行う方法を見つけただけで、間違いなく役立ちます!
ジェイソン

すべてのCodehausサービスは終了しました。リンクが壊れています。
naXa 2016年

2

AOP / AspectJとjcabi-aspectsの@Loggableアノテーションを使用すると、簡単かつコンパクトに実行できます。

@Loggable(Loggable.DEBUG)
public String getSomeResult() {
  // return some value
}

このメソッドへのすべての呼び出しは、DEBUGロギングレベルでSLF4Jロギング機能に送信されます。また、すべてのログメッセージには実行時間が含まれます。


2

Javaで実行時間を見つける方法はいくつかあります。

1)System.nanoTime()

long startTime = System.nanoTime();
.....your code....
long endTime   = System.nanoTime();
long totalTime = endTime - startTime;
System.out.println("Execution time in nanoseconds  : " + totalTime);
System.out.println("Execution time in milliseconds : " + totalTime / 1000000);

2)System.currentTimeMillis()

long startTime = System.currentTimeMillis();
.....your code....
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds  : " + totalTime);

3)Instant.now()

long startTime = Instant.now().toEpochMilli();
.....your code....
long endTime = Instant.now().toEpochMilli();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds: " + totalTime);

または

Instant start = Instant.now();
.....your code....
Instant end = Instant.now();
Duration interval = Duration.between(start, end);
System.out.println("Execution time in seconds: " +interval.getSeconds());

4)Date.getTime()

long startTime = new Date().getTime();
.....your code....
long endTime = new Date().getTime();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds: " + totalTime);

1

startTime=System.currentTimeMillis()ループの先頭で、開始時間にlongを使用します

long endTime= System.currentTimeMillis();ループの終わりの外側に置きます。ミリ秒単位のランタイムを取得するには、値を減算する必要があります。

ナノ秒単位の時間が必要な場合は、チェックアウトしてください System.nanoTime()


1

測定したいコードをラムダとして/ラムダとして受け取る高階関数を作成しました:

class Utils {

    public static <T> T timeIt(String msg, Supplier<T> s) {
        long startTime = System.nanoTime();
        T t = s.get();
        long endTime = System.nanoTime();
        System.out.println(msg + ": " + (endTime - startTime) + " ns");
        return t;
    }

    public static void timeIt(String msg, Runnable r) {
       timeIt(msg, () -> {r.run(); return null; });
    }
}

そのように呼んでください:

Utils.timeIt("code 0", () ->
        System.out.println("Hallo")
);

// in case you need the result of the lambda
int i = Utils.timeIt("code 1", () ->
        5 * 5
);

出力:

コード0:180528 ns
コード1:12003 ns

冗長性を削減するのを手伝ってくれたAndyTurnerに特に感謝します。こちらをご覧ください



0

Perf4Jを試すこともできます。これは、探していることを実行するための優れた方法であり、設定された期間における平均、最小、最大、標準偏差、1秒あたりのトランザクション数などの集約されたパフォーマンス統計に役立ちます。http://perf4j.codehaus.org/devguide.htmlからの抜粋:

StopWatch stopWatch = new LoggingStopWatch();

try {
    // the code block being timed - this is just a dummy example
    long sleepTime = (long)(Math.random() * 1000L);
    Thread.sleep(sleepTime);
    if (sleepTime > 500L) {
        throw new Exception("Throwing exception");
    }

    stopWatch.stop("codeBlock2.success", "Sleep time was < 500 ms");
} catch (Exception e) {
    stopWatch.stop("codeBlock2.failure", "Exception was: " + e);
}

出力:

INFO: start[1230493236109] time[447] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493236719] time[567] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493237286] time[986] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493238273] time[194] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493238467] time[463] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493238930] time[310] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239241] time[610] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493239852] time[84] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239937] time[30] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239968] time[852] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]

0
public class someClass
{
   public static void main(String[] args) // your app start point
   {
       long start = java.util.Calendar.getInstance().getTimeInMillis();

       ... your stuff ...

       long end = java.util.Calendar.getInstance().getTimeInMillis();
       System.out.println("it took this long to complete this stuff: " + (end - start) + "ms");
   }
}

0

System.currentTimeMillis()を使用することは、これを行う適切な方法です。ただし、コマンドラインを使用していて、プログラム全体の時間をほぼ迅速に計りたい場合は、次のことを考慮してください。

time java App

これにより、コードを変更したり、アプリの時間を変更したりする必要がなくなります。


これは、コードの実行方法によって異なります。サーバーを実行しているコードの一部である場合は、正しくない起動時間を含めることになります。
Arun Ramakrishnan 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.