Javaプログラムの実行時間をどのように計りますか?これを行うためにどのクラスを使用すべきかわかりません。
私はちょっと次のようなものを探しています:
// Some timer starts here
for (int i = 0; i < length; i++) {
// Do something
}
// End timer here
System.out.println("Total execution time: " + totalExecutionTime);
回答:
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));
finalは、誤って割り当てることができないという利点があります(また、匿名クラスアクセスなどの他の利点もあります)。このコードでは、違いはありません。すべてを作成しfinal、final必要な場合にのみ統合することは、かなり一般的な方法です。
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
現在のシステム時刻をミリ秒単位で取得します。
final long startTime = System.currentTimeMillis();
次に、これから行うことを実行します。
for (int i = 0; i < length; i++) {
// Do something
}
次に、どのくらいの時間がかかったかがわかります。
final long elapsedTimeMillis = System.currentTimeMillis() - startTime;
を利用できますSystem#nanoTime()。実行の前後にそれを取得し、計算を行うだけです。System#currentTimeMillis()精度が高いため、上記の方が適しています。使用するハードウェアとプラットフォームによっては、経過時間に誤ったギャップが生じる可能性があります。ここで、Windows上のCore2Duoでは、約0〜15ミリ秒の間、実際には何も計算できません。
より高度なツールはプロファイラーです。
nanoTime()1つの問題があります(少なくともWindowsでは)。タイムスタンプはプロセッサコアに固有です。あるコアで「開始」タイムスタンプを取得し、別のコアで「停止」タイムスタンプを取得したため、実行時間が負のプログラムがありました。
単純なものの場合、System.currentTimeMillis()が機能します。
実際には、IDEが「t0」と入力すると、次の行が生成されるように設定されていることがよくあります。
final long t0 = System.currentTimeMillis()
ただし、より複雑な場合は、次のような統計的な時間測定を使用することをお勧めします(少し下にスクロールして、標準偏差などを含めて表現された時間測定を確認します)。
AOP / AspectJとjcabi-aspectsの@Loggableアノテーションを使用すると、簡単かつコンパクトに実行できます。
@Loggable(Loggable.DEBUG)
public String getSomeResult() {
// return some value
}
このメソッドへのすべての呼び出しは、DEBUGロギングレベルでSLF4Jロギング機能に送信されます。また、すべてのログメッセージには実行時間が含まれます。
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);
測定したいコードをラムダとして/ラムダとして受け取る高階関数を作成しました:
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に特に感謝します。こちらをご覧ください。
をご覧くださいSystem.currentTimeMillis()。
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]
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");
}
}
System.currentTimeMillis()を使用することは、これを行う適切な方法です。ただし、コマンドラインを使用していて、プログラム全体の時間をほぼ迅速に計りたい場合は、次のことを考慮してください。
time java App
これにより、コードを変更したり、アプリの時間を変更したりする必要がなくなります。