Jak oceniasz czas wykonania programu Java? Nie jestem pewien, jakiej klasy powinienem użyć, aby to zrobić.
Szukam czegoś takiego:
// Some timer starts here
for (int i = 0; i < length; i++) {
// Do something
}
// End timer here
System.out.println("Total execution time: " + totalExecutionTime);
final
ma tę zaletę, że nie można jej przypadkowo przypisać (a także innych korzyści, takich jak anonimowy dostęp do klas itp.). W tym kodzie nie miałoby to znaczenia. Dość powszechną praktyką jest robienie wszystkiegofinal
ifinal
łączenie go tylko w razie potrzeby.Należy pamiętać, że istnieją pewne problemy, w przypadku
System#nanoTime()
których nie można niezawodnie używać na wielordzeniowych procesorach do rejestrowania czasu, który upłynął ... każdy rdzeń ma własny TSC ( licznik znaczników czasu ): ten licznik jest używany do uzyskania czasu nano (tak naprawdę jest liczba taktów od momentu uruchomienia procesora).W związku z tym, jeśli system operacyjny nie wykona pewnego dopasowania czasu TSC, aby utrzymać synchronizację rdzeni, to jeśli wątek zostanie zaplanowany na jednym rdzeniu, gdy zostanie odczytany początkowy czas, a następnie zostanie przełączony na inny rdzeń, względny czas może sporadycznie wydawać się przeskoczyć wstecz i naprzód.
Zauważyłem to jakiś czas temu na AMD / Solaris, gdzie czasy, które upłynęły między dwoma punktami czasowymi, czasami wracały jako wartości ujemne lub nieoczekiwanie duże liczby dodatnie. Była łatka na jądro Solaris i ustawienie BIOS wymagane do wymuszenia AMD PowerNow! off, który wydawał się go rozwiązać.
Ponadto istnieje (AFAIK) jak dotąd nie naprawiony błąd podczas korzystania z języka Java
System#nanoTime()
w środowisku VirtualBox; powodując dla nas różnego rodzaju dziwne, sporadyczne problemy z gwintowaniem, ponieważ większośćjava.util.concurrency
pakietu opiera się na nano-czasie.Zobacz też:
Czy System.nanoTime () jest całkowicie bezużyteczny? http://vbox.innotek.de/pipermail/vbox-trac/2010-J January/135631.html
źródło
Otrzymujesz aktualny czas systemowy w milisekundach:
final long startTime = System.currentTimeMillis();
Następnie robisz to, co masz zamiar zrobić:
for (int i = 0; i < length; i++) { // Do something }
Następnie widzisz, ile czasu to zajęło:
final long elapsedTimeMillis = System.currentTimeMillis() - startTime;
źródło
Możesz skorzystać z
System#nanoTime()
. Zdobądź to przed i po egzekucji i po prostu zrób matematykę. Jest preferowany powyżej,System#currentTimeMillis()
ponieważ ma lepszą precyzję. W zależności od używanego sprzętu i platformy, w przeciwnym razie możesz otrzymać nieprawidłową przerwę w upływającym czasie. Tutaj z Core2Duo w systemie Windows, między około 0 a ~ 15 ms właściwie nie można nic obliczyć.Bardziej zaawansowanym narzędziem jest profiler .
źródło
nanoTime()
ma jeden problem (przynajmniej w systemie Windows); sygnatura czasowa jest specyficzna dla rdzenia procesora. Miałem program, który miał ujemny czas wykonania, ponieważ miał znacznik czasu „start” na jednym rdzeniu i znacznik czasu „stop” na innym rdzeniu.W przypadku prostych rzeczy może działać System.currentTimeMillis () .
Właściwie jest tak często, że moje IDE jest skonfigurowane tak, że po wpisaniu "t0" generuje mi następujący wiersz:
final long t0 = System.currentTimeMillis()
Ale w przypadku bardziej skomplikowanych rzeczy prawdopodobnie będziesz chciał użyć statystycznych pomiarów czasu, jak tutaj (przewiń w dół i spójrz na wyrażone pomiary czasu, w tym odchylenia standardowe itp.):
http://perf4j.codehaus.org/devguide.html
źródło
Używając AOP / AspectJ i
@Loggable
adnotacji z jcabi-Aspekty , możesz to zrobić łatwo i kompaktowo:@Loggable(Loggable.DEBUG) public String getSomeResult() { // return some value }
Każde wywołanie tej metody będzie wysyłane do narzędzia logowania SLF4J z
DEBUG
poziomem logowania. Każdy komunikat dziennika będzie zawierał czas wykonania.źródło
Oto kilka sposobów na znalezienie czasu wykonania w Javie:
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);
lub
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);
źródło
użyj długiego
startTime=System.currentTimeMillis()
czasu rozpoczęcia, na górze pętliumieścić
long endTime= System.currentTimeMillis();
poza końcem pętli. Będziesz musiał odjąć wartości, aby uzyskać czas działania w milisekundach.Jeśli chcesz mieć czas w nanosekundach, sprawdź
System.nanoTime()
źródło
Stworzyłem funkcję wyższego rzędu, która przyjmuje kod, który chcesz zmierzyć w / jako lambdę:
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; }); } }
Nazwij to tak:
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 );
Wynik:
Specjalne podziękowania dla Andy'ego Turnera, który pomógł mi zmniejszyć liczbę zwolnień. Zobacz tutaj .
źródło
Spójrz na
System.currentTimeMillis()
.źródło
Możesz także wypróbować Perf4J. Jest to zgrabny sposób robienia tego, czego szukasz, i pomaga w zagregowanych statystykach wydajności, takich jak średnia, minimalna, maksymalna, odchylenie standardowe i liczba transakcji na sekundę w określonym przedziale czasu. Wyciąg z 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); }
Wynik:
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]
źródło
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"); } }
źródło
Użycie System.currentTimeMillis () jest właściwym sposobem zrobienia tego. Ale jeśli używasz wiersza poleceń i chcesz w przybliżeniu i szybko ustawić czas dla całego programu, pomyśl o:
co pozwala nie modyfikować kodu i czasu aplikacji.
źródło