Wie kann ich die Ausführung einer Methode in Java zeitlich festlegen?

834
  1. Wie erhalte ich die Ausführungszeit einer Methode?
  2. Gibt es eine TimerUtility-Klasse für Dinge wie das Timing, wie lange eine Aufgabe dauert usw.?

Die meisten Suchanfragen bei Google geben Ergebnisse für Timer zurück, die Threads und Aufgaben planen, was ich nicht möchte.

Oger Psalm33
quelle
Die JAMon-API ist eine kostenlose, einfache, leistungsstarke, threadsichere Java-API, mit der Entwickler die Leistung und Skalierbarkeit von Produktionsanwendungen einfach überwachen können. JAMon verfolgt Treffer, Ausführungszeiten (total, avg, min, max, std dev) und mehr. http://jamonapi.sourceforge.net/ herunterladen: http://sourceforge.net/project/showfiles.php?group_id=96550
Mike Pone
1
Vielleicht möchten Sie sich auch die Apache Commons Lang StopWatch- Klasse ansehen . Eine einfache, aber nützliche Utility-Klasse.
Später ähnlich Frage: Wie schreibe ich einen korrekten Mikro-Benchmark in Java?
Basil Bourque
Ja, StopWatch ist dafür großartig.
Shubham Pandey
Java 8 mit InstantKlasse: stackoverflow.com/a/30975902/1216775
akhil_mittal

Antworten:

1207

Es gibt immer den altmodischen Weg:

long startTime = System.nanoTime();
methodToTime();
long endTime = System.nanoTime();

long duration = (endTime - startTime);  //divide by 1000000 to get milliseconds.
Diastrophismus
quelle
233
Eigentlich ist es "neumodisch", weil Sie nanoTime verwendet haben, das erst mit java5 hinzugefügt wurde
John Gardner
11
Dies (oder die Verwendung von System.currentTimeMillis ()) scheint die Art und Weise zu sein, wie es normalerweise in Java gemacht wird ... die ich sowieso gesehen habe. Es überrascht mich immer noch leicht, dass es keine schicke eingebaute Klasse gibt, wie Timer t = new Timer (); String s = t.getElapsed (Format); etc ...
Ogre Psalm33
18
nanoTime garantiert keine bessere Genauigkeit als currentTimeMillis (), obwohl dies normalerweise der Fall ist. forums.sun.com/thread.jspa?messageID=9460663 und simongbrown.com/blog/2007/08/20/…
James Schek
10
Natürlich ist es immer wichtig, sich an die Fallstricke des Mikro-Benchmarking zu erinnern, wie z. B. Compiler- / JVM-Optimierungen, die das Ergebnis verzerren können = 8-)
Yuval
18
Ein finally-Block ist nicht erforderlich, da endTime nicht verwendet wird, wenn eine Ausnahme ausgelöst wird.
Peter Lawrey
197

Ich gehe mit der einfachen Antwort. Funktioniert bei mir.

long startTime = System.currentTimeMillis();

doReallyLongThing();

long endTime = System.currentTimeMillis();

System.out.println("That took " + (endTime - startTime) + " milliseconds");

Es funktioniert ganz gut. Die Auflösung ist offensichtlich nur auf die Millisekunde genau, Sie können es mit System.nanoTime () besser machen. Es gibt einige Einschränkungen für beide (Zeitplanpläne des Betriebssystems usw.), aber dies funktioniert ziemlich gut.

Durchschnitt über ein paar Läufe (je mehr desto besser) und Sie erhalten eine anständige Vorstellung.

MBCook
quelle
51
Tatsächlich ist System.currentTimeMillis () nur über 15 ms genau. Für wirklich niedrige Werte kann man nicht vertrauen. Die Lösung hierfür (wie erwähnt) ist System.nanoTime ();
Steve g
Ok, ich wollte dies als offizielle Antwort akzeptieren, bis ich Steve gs Kommentar gelesen hatte. Großartiger Leckerbissen, Steve!
Oger Psalm33
4
nanoTime () garantiert keine bessere Genauigkeit als currentTimeMillis, aber viele JVM-Implementierungen weisen mit nanoTime eine bessere Genauigkeit auf.
James Schek
5
@JamesSchek Sie müssen wirklich auf Ihren Wortlaut achten, wie ich bereits an anderer Stelle zu diesem identischen Kommentar erwähnt habe. nanoTimeist garantiert mindestens so entschlossen wie currentTimeMillis. docs.oracle.com/javase/7/docs/api/java/lang/…
b1nary.atr0phy
Der einzige kleine Vorteil von currentTimeMillisist, dass es sich um einen tatsächlichen Zeitstempel handelt und auch zum Protokollieren von Start- / Endzeiten verwendet werden kann, während nanoTime"nur zum Messen der verstrichenen Zeit verwendet werden kann und nicht mit einem anderen Begriff der System- oder Wanduhrzeit zusammenhängt . "
Brad Parks
177

Komm schon Leute! Niemand erwähnte die Guave- Methode, um das zu tun (was wohl großartig ist):

import com.google.common.base.Stopwatch;

Stopwatch timer = Stopwatch.createStarted();
//method invocation
LOG.info("Method took: " + timer.stop());

Das Schöne ist, dass Stopwatch.toString () die Zeiteinheiten für die Messung gut auswählt. Das heißt, wenn der Wert klein ist, werden 38 ns ausgegeben, wenn er lang ist, werden 5 m 3 s angezeigt

Noch schöner:

Stopwatch timer = Stopwatch.createUnstarted();
for (...) {
   timer.start();
   methodToTrackTimeFor();
   timer.stop();
   methodNotToTrackTimeFor();
}
LOG.info("Method took: " + timer);

Hinweis: Für Google Guava ist Java 1.6+ erforderlich

Dmitry Kalashnikov
quelle
21
Leider ist Guavas Stoppuhr nicht threadsicher. Ich habe das auf die harte Tour gelernt.
Dexter Legaspi
6
@DexterLegaspi Würde mich sehr für deine Erfahrung interessieren! Möchtest du teilen?
Siddhartha
1
Die parallele Verwendung der Stoppuhr würde dazu führen, dass Sie start()mehrmals hintereinander anrufen (dasselbe gilt für stop()).
Mingwei Samuel
141

Verwenden von Instant und Duration aus der neuen API von Java 8,

Instant start = Instant.now();
Thread.sleep(5000);
Instant end = Instant.now();
System.out.println(Duration.between(start, end));

Ausgänge,

PT5S
Sufiyan Ghori
quelle
2
Danke, wie kann ich das Ergebnis ausgeben, ohne den PT vorne zu haben?
Java123999
1
Das Problem mit der Methode ist, dass Instant keine Milli- und Nano-Sekundengenauigkeit hat. Ref: stackoverflow.com/questions/20689055/…
prashantsunkari
8
@ java123999: Sie können anrufen Duration.between(start, end).getSeconds(). Durationhat auch Methoden zum Konvertieren in andere Zeiteinheiten, z. B. toMillis()die in Millisekunden konvertieren.
Emil Lunde
100

Sammelte alle möglichen Wege zusammen an einem Ort.

Datum

Date startDate = Calendar.getInstance().getTime();
long d_StartTime = new Date().getTime();
Thread.sleep(1000 * 4);
Date endDate = Calendar.getInstance().getTime();
long d_endTime = new Date().getTime();
System.out.format("StartDate : %s, EndDate : %s \n", startDate, endDate);
System.out.format("Milli = %s, ( D_Start : %s, D_End : %s ) \n", (d_endTime - d_StartTime),d_StartTime, d_endTime);

System. currentTimeMillis ()

long startTime = System.currentTimeMillis();
Thread.sleep(1000 * 4);
long endTime = System.currentTimeMillis();
long duration = (endTime - startTime);  
System.out.format("Milli = %s, ( S_Start : %s, S_End : %s ) \n", duration, startTime, endTime );
System.out.println("Human-Readable format : "+millisToShortDHMS( duration ) );

Vom Menschen lesbares Format

public static String millisToShortDHMS(long duration) {
    String res = "";    // java.util.concurrent.TimeUnit;
    long days       = TimeUnit.MILLISECONDS.toDays(duration);
    long hours      = TimeUnit.MILLISECONDS.toHours(duration) -
                      TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));
    long minutes    = TimeUnit.MILLISECONDS.toMinutes(duration) -
                      TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));
    long seconds    = TimeUnit.MILLISECONDS.toSeconds(duration) -
                      TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));
    long millis     = TimeUnit.MILLISECONDS.toMillis(duration) - 
                      TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(duration));

    if (days == 0)      res = String.format("%02d:%02d:%02d.%04d", hours, minutes, seconds, millis);
    else                res = String.format("%dd %02d:%02d:%02d.%04d", days, hours, minutes, seconds, millis);
    return res;
}

Guave: Google Stopwatch JAR «Ein Ziel von Stopwatch ist es, die verstrichene Zeit in Nanosekunden zu messen.

com.google.common.base.Stopwatch g_SW = Stopwatch.createUnstarted();
g_SW.start();
Thread.sleep(1000 * 4);
g_SW.stop();
System.out.println("Google StopWatch  : "+g_SW);

Apache Commons Lang JAR « StopWatch bietet eine praktische API für Timings.

org.apache.commons.lang3.time.StopWatch sw = new StopWatch();
sw.start();     
Thread.sleep(1000 * 4);     
sw.stop();
System.out.println("Apache StopWatch  : "+ millisToShortDHMS(sw.getTime()) );

JODA- ZEIT

public static void jodaTime() throws InterruptedException, ParseException{
    java.text.SimpleDateFormat ms_SDF = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
    String start = ms_SDF.format( new Date() ); // java.util.Date

    Thread.sleep(10000);

    String end = ms_SDF.format( new Date() );       
    System.out.println("Start:"+start+"\t Stop:"+end);

    Date date_1 = ms_SDF.parse(start);
    Date date_2 = ms_SDF.parse(end);        
    Interval interval = new org.joda.time.Interval( date_1.getTime(), date_2.getTime() );
    Period period = interval.toPeriod(); //org.joda.time.Period

    System.out.format("%dY/%dM/%dD, %02d:%02d:%02d.%04d \n", 
        period.getYears(), period.getMonths(), period.getDays(),
        period.getHours(), period.getMinutes(), period.getSeconds(), period.getMillis());
}

Java-Datums- / Uhrzeit-API von Java 8 «Ein Duration- Objekt repräsentiert einen Zeitraum zwischen zwei Instant- Objekten.

Instant start = java.time.Instant.now();
    Thread.sleep(1000);
Instant end = java.time.Instant.now();
Duration between = java.time.Duration.between(start, end);
System.out.println( between ); // PT1.001S
System.out.format("%dD, %02d:%02d:%02d.%04d \n", between.toDays(),
        between.toHours(), between.toMinutes(), between.getSeconds(), between.toMillis()); // 0D, 00:00:01.1001 

Spring Framework bietet die StopWatch- Dienstprogrammklasse zum Messen der verstrichenen Zeit in Java.

StopWatch sw = new org.springframework.util.StopWatch();
sw.start("Method-1"); // Start a named task
    Thread.sleep(500);
sw.stop();

sw.start("Method-2");
    Thread.sleep(300);
sw.stop();

sw.start("Method-3");
    Thread.sleep(200);
sw.stop();

System.out.println("Total time in milliseconds for all tasks :\n"+sw.getTotalTimeMillis());
System.out.println("Table describing all tasks performed :\n"+sw.prettyPrint());

System.out.format("Time taken by the last task : [%s]:[%d]", 
        sw.getLastTaskName(),sw.getLastTaskTimeMillis());

System.out.println("\n Array of the data for tasks performed « Task Name: Time Taken");
TaskInfo[] listofTasks = sw.getTaskInfo();
for (TaskInfo task : listofTasks) {
    System.out.format("[%s]:[%d]\n", 
            task.getTaskName(), task.getTimeMillis());
}

Ausgabe:

Total time in milliseconds for all tasks :
999
Table describing all tasks performed :
StopWatch '': running time (millis) = 999
-----------------------------------------
ms     %     Task name
-----------------------------------------
00500  050%  Method-1
00299  030%  Method-2
00200  020%  Method-3

Time taken by the last task : [Method-3]:[200]
 Array of the data for tasks performed « Task Name: Time Taken
[Method-1]:[500]
[Method-2]:[299]
[Method-3]:[200]
Yash
quelle
Stoppuhr von Guava, Apache Commons und Spring Framework sind nicht threadsicher. Nicht sicher für den Produktionsgebrauch.
Deepak Puthraya
@DeepakPuthraya Welche Bibliothek soll dann verwendet werden, die für die Produktion sicher ist?
Gaurav
1
@DeepakPuthraya Sie können die von Java 8 bereitgestellte Java-API für Datum und Uhrzeit verwenden. Welches ist einfach.
Yash
IMO würde dieser Beitrag davon profitieren, wenn jede Lösung auch die Ausgabe der Systemausgänge anzeigen würde.
BAERUS
87

Verwenden Sie einen Profiler (JProfiler, Netbeans Profiler, Visual VM, Eclipse Profiler usw.). Sie erhalten die genauesten Ergebnisse und sind am wenigsten aufdringlich. Sie verwenden den integrierten JVM-Mechanismus für die Profilerstellung, der Ihnen bei Bedarf zusätzliche Informationen wie Stapelspuren, Ausführungspfade und umfassendere Ergebnisse liefert.

Wenn Sie einen vollständig integrierten Profiler verwenden, ist es nicht einfach, eine Methode zu profilieren. Klicken Sie mit der rechten Maustaste auf Profiler -> Zu Stammmethoden hinzufügen. Führen Sie dann den Profiler so aus, als würden Sie einen Testlauf oder einen Debugger durchführen.

James Schek
quelle
Dies war auch ein großartiger Vorschlag und einer dieser "duh" Glühbirnenmomente für mich, als ich diese Antwort las. Unser Projekt verwendet JDeveloper, aber ich habe es überprüft und sicher hat es einen eingebauten Profiler!
Oger Psalm33
2
Von Java 7 Build 40 (glaube ich) enthielten sie den ehemaligen JRockits Flight Recorder zu Java (Suche nach Java Mission Control)
Niels Bech Nielsen
Sicher genug @NielsBechNielsen! oracle.com/technetwork/java/javaseproducts/mission-control/…
Ogre Psalm33
Wie kann ich beispielsweise die Ausführung einer Methode in Java durch Visual VM abrufen?
Okwap
41

Dies ist wahrscheinlich nicht das, was Sie von mir wollten, aber dies ist eine gute Verwendung von AOP. Peitsche einen Proxy-Interceptor um deine Methode und mache das Timing dort.

Das Was, Warum und Wie von AOP würde leider den Rahmen dieser Antwort sprengen, aber so würde ich es wahrscheinlich tun.

Bearbeiten: Hier ist ein Link zu Spring AOP, um Ihnen den Einstieg zu erleichtern, wenn Sie daran interessiert sind. Dies ist die am leichtesten zugängliche Implementierung von AOP, die Iive für Java findet.

Angesichts der sehr einfachen Vorschläge aller anderen sollte ich hinzufügen, dass AOP für den Fall gedacht ist, dass Sie nicht möchten, dass Dinge wie das Timing in Ihren Code eindringen. Aber in vielen Fällen ist diese Art von einfachem und leichtem Ansatz in Ordnung.

Skaffman
quelle
3
Hier ist ein Tutorial, wie man das mit Spring macht: veerasundar.com/blog/2010/01/…
David Tinker
39

System.currentTimeMillis();IST KEIN guter Ansatz, um die Leistung Ihrer Algorithmen zu messen. Es misst die Gesamtzeit, die Sie als Benutzer auf dem Computerbildschirm verbringen. Es enthält auch Zeit, die von allem anderen verbraucht wird, das im Hintergrund auf Ihrem Computer ausgeführt wird. Dies kann einen großen Unterschied machen, wenn auf Ihrer Workstation viele Programme ausgeführt werden.

Der richtige Ansatz ist die Verwendung eines java.lang.managementPakets.

Von der Website http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking :

  • "Benutzerzeit" ist die Zeit, die für die Ausführung des Codes Ihrer Anwendung aufgewendet wird.
  • "Systemzeit" ist die Zeit, die für die Ausführung von Betriebssystemcode im Namen Ihrer Anwendung aufgewendet wird (z. B. für E / A).

getCpuTime() Methode gibt Ihnen die Summe dieser:

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;

public class CPUUtils {

    /** Get CPU time in nanoseconds. */
    public static long getCpuTime( ) {
        ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
        return bean.isCurrentThreadCpuTimeSupported( ) ?
            bean.getCurrentThreadCpuTime( ) : 0L;
    }

    /** Get user time in nanoseconds. */
    public static long getUserTime( ) {
        ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
        return bean.isCurrentThreadCpuTimeSupported( ) ?
            bean.getCurrentThreadUserTime( ) : 0L;
    }

    /** Get system time in nanoseconds. */
    public static long getSystemTime( ) {
        ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
        return bean.isCurrentThreadCpuTimeSupported( ) ?
            (bean.getCurrentThreadCpuTime( ) - bean.getCurrentThreadUserTime( )) : 0L;
    }

}
TondaCZE
quelle
4
Dies ist definitiv ein guter Punkt, da die "Benutzerzeit" (Wanduhrzeit) nicht immer ein gutes Maß für die Leistung ist, insbesondere in einem Multithread-Programm.
Oger Psalm33
Dies ist die Antwort, die ich suche.
ZhaoGang
30

Mit Java 8 können Sie auch so etwas mit allen normalen Methoden machen :

Object returnValue = TimeIt.printTime(() -> methodeWithReturnValue());
//do stuff with your returnValue

mit TimeIt like:

public class TimeIt {

public static <T> T printTime(Callable<T> task) {
    T call = null;
    try {
        long startTime = System.currentTimeMillis();
        call = task.call();
        System.out.print((System.currentTimeMillis() - startTime) / 1000d + "s");
    } catch (Exception e) {
        //...
    }
    return call;
}
}

Mit dieser Methode können Sie überall in Ihrem Code einfach Zeit messen, ohne ihn zu beschädigen. In diesem einfachen Beispiel drucke ich einfach die Zeit. Mögen Sie einen Schalter für TimeIt hinzufügen, z. B. um nur die Zeit im DebugMode oder so etwas zu drucken.

Wenn Sie mit Function arbeiten , können Sie Folgendes tun:

Function<Integer, Integer> yourFunction= (n) -> {
        return IntStream.range(0, n).reduce(0, (a, b) -> a + b);
    };

Integer returnValue = TimeIt.printTime2(yourFunction).apply(10000);
//do stuff with your returnValue

public static <T, R> Function<T, R> printTime2(Function<T, R> task) {
    return (t) -> {
        long startTime = System.currentTimeMillis();
        R apply = task.apply(t);
        System.out.print((System.currentTimeMillis() - startTime) / 1000d
                + "s");
        return apply;
    };
}
Stefan
quelle
Das sieht viel besser aus als andere Lösungen. Es ist näher an Spring AOP und dennoch leichter. Echter Java 8 Weg! +1 Danke!
Amit Kumar
Vielleicht sieht das für dich gut aus, weil Stefan ausgefallene neue Java-Funktionen verwendet. Aber ich denke, das ist wirklich schwer zu lesen und zu verstehen.
Stimpson Cat
18

Wir können auch die StopWatch-Klasse von Apache Commons verwenden, um die Zeit zu messen.

Beispielcode

org.apache.commons.lang.time.StopWatch sw = new org.apache.commons.lang.time.StopWatch();

System.out.println("getEventFilterTreeData :: Start Time : " + sw.getTime());
sw.start();

// Method execution code

sw.stop();
System.out.println("getEventFilterTreeData :: End Time : " + sw.getTime());
Narayan
quelle
15

Nur eine kleine Wendung, wenn Sie keine Werkzeuge verwenden und Methoden mit geringer Ausführungszeit zeitlich festlegen möchten: Führen Sie sie mehrmals aus, wobei Sie die Anzahl der Ausführungen jedes Mal verdoppeln, bis Sie eine Sekunde oder so erreichen. Daher hat weder die Zeit des Aufrufs von System.nanoTime usw. noch die Genauigkeit von System.nanoTime einen großen Einfluss auf das Ergebnis.

    int runs = 0, runsPerRound = 10;
    long begin = System.nanoTime(), end;
    do {
        for (int i=0; i<runsPerRound; ++i) timedMethod();
        end = System.nanoTime();
        runs += runsPerRound;
        runsPerRound *= 2;
    } while (runs < Integer.MAX_VALUE / 2 && 1000000000L > end - begin);
    System.out.println("Time for timedMethod() is " + 
        0.000000001 * (end-begin) / runs + " seconds");

Natürlich gelten die Einschränkungen bei der Verwendung der Wanduhr: Einflüsse der JIT-Kompilierung, mehrere Threads / Prozesse usw. Daher müssen Sie die Methode zuerst viele Male ausführen , damit der JIT-Compiler seine Arbeit erledigt, und dann Wiederholen Sie diesen Test mehrmals und nehmen Sie die niedrigste Ausführungszeit.

Hans-Peter Störr
quelle
13

Zu diesem Zweck verwenden wir AspectJ- und Java-Annotationen. Wenn wir die Ausführungszeit für eine Methode kennen müssen, kommentieren wir sie einfach. Eine erweiterte Version könnte eine eigene Protokollebene verwenden, die zur Laufzeit aktiviert und deaktiviert werden kann.

public @interface Trace {
  boolean showParameters();
}

@Aspect
public class TraceAspect {
  [...]
  @Around("tracePointcut() && @annotation(trace) && !within(TraceAspect)")
  public Object traceAdvice ( ProceedingJintPoint jP, Trace trace ) {

    Object result;
    // initilize timer

    try { 
      result = jp.procced();
    } finally { 
      // calculate execution time 
    }

    return result;
  }
  [...]
}

quelle
13

JEP 230: Microbenchmark Suite

Zu Ihrer Information , JEP 230: Microbenchmark Suite ist ein OpenJDK- Projekt für:

Fügen Sie dem JDK-Quellcode eine grundlegende Suite von Mikrobenchmarks hinzu, und erleichtern Sie Entwicklern das Ausführen vorhandener Mikrobenchmarks und das Erstellen neuer.

Diese Funktion ist in Java 12 verfügbar .

Java Microbenchmark Harness (JMH)

Schauen Sie sich für frühere Java-Versionen das JMH- Projekt (Java Microbenchmark Harness) an , auf dem JEP 230 basiert.

Basil Bourque
quelle
11

Wirklich guter Code.

http://www.rgagnon.com/javadetails/java-0585.html

import java.util.concurrent.TimeUnit;

long startTime = System.currentTimeMillis();
........
........
........
long finishTime = System.currentTimeMillis();

String diff = millisToShortDHMS(finishTime - startTime);


  /**
   * converts time (in milliseconds) to human-readable format
   *  "<dd:>hh:mm:ss"
   */
  public static String millisToShortDHMS(long duration) {
    String res = "";
    long days  = TimeUnit.MILLISECONDS.toDays(duration);
    long hours = TimeUnit.MILLISECONDS.toHours(duration)
                   - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));
    long minutes = TimeUnit.MILLISECONDS.toMinutes(duration)
                     - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));
    long seconds = TimeUnit.MILLISECONDS.toSeconds(duration)
                   - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));
    if (days == 0) {
      res = String.format("%02d:%02d:%02d", hours, minutes, seconds);
    }
    else {
      res = String.format("%dd%02d:%02d:%02d", days, hours, minutes, seconds);
    }
    return res;
  }
Eisberg
quelle
3
Eigentlich war die Frage, wie man die Zeit berechnet, die eine Methode benötigt, und nicht, wie man sie formatiert. Diese Frage ist jedoch ziemlich alt (fast vier Jahre!). Vermeiden Sie die Wiederbelebung alter Threads, es sei denn, die Antwort fügt den vorhandenen Antworten etwas Neues und Bedeutendes hinzu.
Leigh
1
Und um die verbleibenden Millis am Ende hinzuzufügen, nehmen Sie die folgenden Änderungen vor: long millis = TimeUnit.MILLISECONDS.toMillis(duration) - TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(duration)); if (days == 0) { res = String.format("%02d:%02d:%02d.%02d", hours, minutes, seconds, millis); } else { res = String.format("%dd%02d:%02d:%02d.%02d", days, hours, minutes, seconds, millis); }
Rick Barkhouse
10

Sie können Perf4j verwenden . Sehr cooles Dienstprogramm. Die Verwendung ist einfach

String watchTag = "target.SomeMethod";
StopWatch stopWatch = new LoggingStopWatch(watchTag);
Result result = null; // Result is a type of a return value of a method
try {
    result = target.SomeMethod();
    stopWatch.stop(watchTag + ".success");
} catch (Exception e) {
    stopWatch.stop(watchTag + ".fail", "Exception was " + e);
    throw e; 
}

Weitere Informationen finden Sie im Entwicklerhandbuch

Bearbeiten: Projekt scheint tot

mergenchik
quelle
1
Perf4j kann auch schöne Statistiken generieren .
Paaske
8
new Timer(""){{
    // code to time 
}}.timeMe();



public class Timer {

    private final String timerName;
    private long started;

    public Timer(String timerName) {
        this.timerName = timerName;
        this.started = System.currentTimeMillis();
    }

    public void timeMe() {
        System.out.println(
        String.format("Execution of '%s' takes %dms.", 
                timerName, 
                started-System.currentTimeMillis()));
    }

}
Maciek Kreft
quelle
1
Das Rollen Ihrer eigenen einfachen Klasse ist eine gute Wahl, wenn Sie das Build-System und das abhängige OTS bereits eingerichtet haben und sich nicht die Mühe machen möchten, ein anderes OTS-Paket zu ziehen, das eine Utility-Timer-Klasse enthält.
Oger Psalm33
7

Grundsätzlich mache ich Variationen davon, aber wenn Sie bedenken, wie die Hotspot-Kompilierung funktioniert, müssen Sie die ersten Messungen verwerfen und sicherstellen, dass Sie die Methode in einer realen (anwendungsspezifischen) Anwendung verwenden, wenn Sie genaue Ergebnisse erzielen möchten.

Wenn die JIT beschließt, sie zu kompilieren, variieren Ihre Zahlen stark. Also sei dir einfach bewusst

Luke
quelle
7

Mit AOP / AspectJ und @LoggableAnmerkungen unter jcabi-Aspekten können Sie dies einfach und kompakt tun:

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

Jeder Aufruf dieser Methode wird an die SLF4J-Protokollierungsfunktion mit DEBUGProtokollierungsstufe gesendet . Und jede Protokollnachricht enthält die Ausführungszeit.

yegor256
quelle
7

Spring bietet eine Dienstprogrammklasse org.springframework.util.StopWatch gemäß JavaDoc:

Einfache Stoppuhr, die das Timing einer Reihe von Aufgaben ermöglicht und die Gesamtlaufzeit und die Laufzeit für jede benannte Aufgabe anzeigt.

Verwendungszweck:

StopWatch stopWatch = new StopWatch("Performance Test Result");

stopWatch.start("Method 1");
doSomething1();//method to test
stopWatch.stop();

stopWatch.start("Method 2");
doSomething2();//method to test
stopWatch.stop();

System.out.println(stopWatch.prettyPrint());

Ausgabe:

StopWatch 'Performance Test Result': running time (millis) = 12829
-----------------------------------------
ms     %     Task name
-----------------------------------------
11907  036%  Method 1
00922  064%  Method 2

Mit Aspekten:

@Around("execution(* my.package..*.*(..))")
public Object logTime(ProceedingJoinPoint joinPoint) throws Throwable {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    Object retVal = joinPoint.proceed();
    stopWatch.stop();
    log.info(" execution time: " + stopWatch.getTotalTimeMillis() + " ms");
    return retVal;
}
Sunil Manheri
quelle
Ist es möglich, dies mit AspectJ zu verwenden?
Zygimantus
7

Ich habe eine Methode geschrieben, um die Ausführungszeit der Methode in einer gut lesbaren Form zu drucken. Die Berechnung der Fakultät von 1 Million dauert beispielsweise ungefähr 9 Minuten. Die Ausführungszeit wird also wie folgt gedruckt:

Execution Time: 9 Minutes, 36 Seconds, 237 MicroSeconds, 806193 NanoSeconds

Der Code ist hier:

public class series
{
    public static void main(String[] args)
    {
        long startTime = System.nanoTime();

        long n = 10_00_000;
        printFactorial(n);

        long endTime = System.nanoTime();
        printExecutionTime(startTime, endTime);

    }

    public static void printExecutionTime(long startTime, long endTime)
    {
        long time_ns = endTime - startTime;
        long time_ms = TimeUnit.NANOSECONDS.toMillis(time_ns);
        long time_sec = TimeUnit.NANOSECONDS.toSeconds(time_ns);
        long time_min = TimeUnit.NANOSECONDS.toMinutes(time_ns);
        long time_hour = TimeUnit.NANOSECONDS.toHours(time_ns);

        System.out.print("\nExecution Time: ");
        if(time_hour > 0)
            System.out.print(time_hour + " Hours, ");
        if(time_min > 0)
            System.out.print(time_min % 60 + " Minutes, ");
        if(time_sec > 0)
            System.out.print(time_sec % 60 + " Seconds, ");
        if(time_ms > 0)
            System.out.print(time_ms % 1E+3 + " MicroSeconds, ");
        if(time_ns > 0)
            System.out.print(time_ns % 1E+6 + " NanoSeconds");
    }
}
Pratik Patil
quelle
6

Es gibt verschiedene Möglichkeiten, dies zu tun. Normalerweise greife ich auf so etwas zurück:

long start = System.currentTimeMillis();
// ... do something ...
long end = System.currentTimeMillis();

oder dasselbe mit System.nanoTime ();

Für etwas mehr auf der Benchmarking-Seite scheint es auch dieses zu geben: http://jetm.void.fm/ Ich habe es jedoch nie versucht.

Horst Gutmann
quelle
6

Sie können die Metrikbibliothek verwenden, die verschiedene Messinstrumente bereitstellt. Abhängigkeit hinzufügen:

<dependencies>
    <dependency>
        <groupId>io.dropwizard.metrics</groupId>
        <artifactId>metrics-core</artifactId>
        <version>${metrics.version}</version>
    </dependency>
</dependencies>

Und konfigurieren Sie es für Ihre Umgebung.

Methoden können mit @Timed kommentiert werden :

@Timed
public void exampleMethod(){
    // some code
}

oder mit Timer umwickeltes Stück Code :

final Timer timer = metricsRegistry.timer("some_name");
final Timer.Context context = timer.time();
// timed code
context.stop();

Aggregierte Metriken können in die Konsole, JMX, CSV oder andere exportiert werden.

@Timed Beispiel für die Ausgabe von Metriken:

com.example.ExampleService.exampleMethod
             count = 2
         mean rate = 3.11 calls/minute
     1-minute rate = 0.96 calls/minute
     5-minute rate = 0.20 calls/minute
    15-minute rate = 0.07 calls/minute
               min = 17.01 milliseconds
               max = 1006.68 milliseconds
              mean = 511.84 milliseconds
            stddev = 699.80 milliseconds
            median = 511.84 milliseconds
              75% <= 1006.68 milliseconds
              95% <= 1006.68 milliseconds
              98% <= 1006.68 milliseconds
              99% <= 1006.68 milliseconds
            99.9% <= 1006.68 milliseconds
Genauso wie
quelle
5

Wenn Sie Wanduhrzeit wollen

long start_time = System.currentTimeMillis();
object.method();
long end_time = System.currentTimeMillis();
long execution_time = end_time - start_time;
David Nehme
quelle
5

Wie "skaffman" sagte, verwenden Sie AOP ODER Sie können das Laufzeit-Bytecode-Weben verwenden, genau wie die Tools zur Abdeckung von Unit-Test-Methoden, um den aufgerufenen Methoden transparent Timing-Informationen hinzuzufügen.

Sie können sich Code ansehen, der von Open Source-Tools wie Emma verwendet wird ( http://downloads.sourceforge.net/emma/emma-2.0.5312-src.zip?modtime=1118607545&big_mirror=0 ). Das andere OpenSource-Coverage-Tool ist http://prdownloads.sourceforge.net/cobertura/cobertura-1.9-src.zip?download .

Wenn Sie es schließlich schaffen, das zu tun, was Sie sich vorgenommen haben, pls. Teile es der Community hier mit deinen Ameisenaufgaben / Gläsern zurück.

anjanb
quelle
4
long startTime = System.currentTimeMillis();
// code goes here
long finishTime = System.currentTimeMillis();
long elapsedTime = finishTime - startTime; // elapsed time in milliseconds
Ryan Rodemoyer
quelle
4

Ich habe den Code von der richtigen Antwort geändert, um das Ergebnis in Sekunden zu erhalten:

long startTime = System.nanoTime();

methodCode ...

long endTime = System.nanoTime();
double duration = (double)(endTime - startTime) / (Math.pow(10, 9));
Log.v(TAG, "MethodName time (s) = " + duration);
Denis Kutlubaev
quelle
4

Sie können die Stoppuhrklasse aus dem Spring Core-Projekt verwenden:

Code:

StopWatch stopWatch = new StopWatch()
stopWatch.start();  //start stopwatch
// write your function or line of code.
stopWatch.stop();  //stop stopwatch
stopWatch.getTotalTimeMillis() ; ///get total time

Dokumentation für die Stoppuhr: Einfache Stoppuhr , die das Timing einer Reihe von Aufgaben ermöglicht und die Gesamtlaufzeit und die Laufzeit für jede benannte Aufgabe anzeigt. Verbirgt die Verwendung von System.currentTimeMillis (), verbessert die Lesbarkeit des Anwendungscodes und verringert die Wahrscheinlichkeit von Berechnungsfehlern. Beachten Sie, dass dieses Objekt nicht threadsicher ist und keine Synchronisation verwendet. Diese Klasse wird normalerweise verwendet, um die Leistung während des Proof-of-Concepts und der Entwicklung zu überprüfen, und nicht als Teil von Produktionsanwendungen.

Praveen Jain
quelle
3

Sie können dies versuchen, wenn Sie nur die Zeit wissen möchten.

long startTime = System.currentTimeMillis();
//@ Method call
System.out.println("Total time [ms]: " + (System.currentTimeMillis() - startTime));    
gifpif
quelle
3

Ok, dies ist eine einfache Klasse, die für ein einfaches Timing Ihrer Funktionen verwendet werden kann. Darunter befindet sich ein Beispiel.

public class Stopwatch {
    static long startTime;
    static long splitTime;
    static long endTime;

    public Stopwatch() {
        start();
    }

    public void start() {
        startTime = System.currentTimeMillis();
        splitTime = System.currentTimeMillis();
        endTime = System.currentTimeMillis();
    }

    public void split() {
        split("");
    }

    public void split(String tag) {
        endTime = System.currentTimeMillis();
        System.out.println("Split time for [" + tag + "]: " + (endTime - splitTime) + " ms");
        splitTime = endTime;
    }

    public void end() {
        end("");
    }
    public void end(String tag) {
        endTime = System.currentTimeMillis();
        System.out.println("Final time for [" + tag + "]: " + (endTime - startTime) + " ms");
    }
}

Anwendungsbeispiel:

public static Schedule getSchedule(Activity activity_context) {
        String scheduleJson = null;
        Schedule schedule = null;
/*->*/  Stopwatch stopwatch = new Stopwatch();

        InputStream scheduleJsonInputStream = activity_context.getResources().openRawResource(R.raw.skating_times);
/*->*/  stopwatch.split("open raw resource");

        scheduleJson = FileToString.convertStreamToString(scheduleJsonInputStream);
/*->*/  stopwatch.split("file to string");

        schedule = new Gson().fromJson(scheduleJson, Schedule.class);
/*->*/  stopwatch.split("parse Json");
/*->*/  stopwatch.end("Method getSchedule"); 
    return schedule;
}

Beispiel für die Konsolenausgabe:

Split time for [file to string]: 672 ms
Split time for [parse Json]: 893 ms
Final time for [get Schedule]: 1565 ms
msysmilu
quelle
3

In Java 8 wird eine neue Klasse mit dem Namen Instanteingeführt. Gemäß Dokument:

Der Moment repräsentiert den Beginn einer Nanosekunde auf der Zeitlinie. Diese Klasse ist nützlich, um einen Zeitstempel zur Darstellung der Maschinenzeit zu generieren. Die Reichweite eines Augenblicks erfordert die Speicherung einer Zahl, die größer als eine lange ist. Um dies zu erreichen, speichert die Klasse eine lange Epoche und eine int, die eine Nanosekunde darstellt, die immer zwischen 0 und 999.999.999 liegt. Die Epochensekunden werden aus der Standard-Java-Epoche von 1970-01-01T00: 00: 00Z gemessen, in der Momente nach der Epoche positive Werte und frühere Momente negative Werte aufweisen. Sowohl für den Epochensekunden- als auch für den Nanosekundenbereich liegt ein größerer Wert immer später auf der Zeitachse als ein kleinerer Wert.

Dies kann verwendet werden als:

Instant start = Instant.now();
try {
    Thread.sleep(7000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
Instant end = Instant.now();
System.out.println(Duration.between(start, end));

Es wird gedruckt PT7.001S.

akhil_mittal
quelle