Bagaimana cara mengatur waktu eksekusi metode di Java?

834
  1. Bagaimana cara saya mendapatkan waktu eksekusi metode?
  2. Apakah ada Timerkelas utilitas untuk hal-hal seperti menghitung berapa lama tugas, dll?

Sebagian besar pencarian di Google menghasilkan hasil untuk timer yang menjadwalkan utas dan tugas, yang bukan yang saya inginkan.

Ogre Psalm33
sumber
JAMon API adalah API Java gratis, sederhana, berkinerja tinggi, aman, yang memungkinkan pengembang untuk dengan mudah memantau kinerja dan skalabilitas aplikasi produksi. JAMon melacak hit, waktu eksekusi (total, rata-rata, minimum, maks, std dev), dan banyak lagi. http://jamonapi.sourceforge.net/ unduh: http://sourceforge.net/project/showfiles.php?group_id=96550
Mike Pone
1
Anda mungkin juga ingin melihat kelas StopWatch Apache Commons Lang . Kelas utilitas yang sederhana namun bermanfaat.
Pertanyaan serupa yang serupa: Bagaimana cara saya menulis benchmark mikro di Jawa?
Basil Bourque
Ya, StopWatch sangat bagus untuk ini.
Shubham Pandey
Java 8 menggunakan Instantkelas: stackoverflow.com/a/30975902/1216775
akhil_mittal

Jawaban:

1208

Selalu ada cara kuno:

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

long duration = (endTime - startTime);  //divide by 1000000 to get milliseconds.
Diastrofisme
sumber
234
sebenarnya, ini "baru" karena Anda menggunakan nanoTime, yang tidak ditambahkan sampai java5
John Gardner
11
Ini (atau menggunakan System.currentTimeMillis ()) tampaknya menjadi cara yang biasanya dilakukan di Jawa ... yang pernah saya lihat. Itu masih agak mengejutkan saya bahwa tidak ada kelas built-in keren, seperti Timer t = Timer baru (); String s = t.getElapsed (format); dll ...
Ogre Psalm33
18
nanoTime tidak menjamin akurasi lebih baik daripada currentTimeMillis (), meskipun biasanya demikian. forums.sun.com/thread.jspa?messageID=9460663 dan simongbrown.com/blog/2007/08/20/…
James
10
Tentu saja, selalu penting untuk mengingat perangkap dari pembandingan-mikro, seperti optimisasi kompiler / JVM yang dapat mendistorsi hasil = 8-)
Yuval
18
Tidak perlu untuk blok akhirnya karena endTime tidak akan digunakan jika pengecualian dilemparkan.
Peter Lawrey
197

Saya pergi dengan jawaban sederhana. Bekerja untukku.

long startTime = System.currentTimeMillis();

doReallyLongThing();

long endTime = System.currentTimeMillis();

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

Ini bekerja dengan sangat baik. Resolusi ini jelas hanya untuk milidetik, Anda dapat melakukannya lebih baik dengan System.nanoTime (). Ada beberapa batasan untuk keduanya (irisan jadwal sistem operasi, dll.) Tetapi ini bekerja cukup baik.

Rata-rata di beberapa berjalan (semakin banyak semakin baik) dan Anda akan mendapatkan ide yang layak.

MBCook
sumber
51
Sebenarnya, System.currentTimeMillis () hanya akurat di atas 15ms. Untuk nilai yang sangat rendah, itu tidak bisa dipercaya. Solusi untuk ini (sebagaimana disebutkan) adalah System.nanoTime ();
Steve g
Ok, saya akan menerima ini sebagai jawaban resmi sampai saya membaca komentar Steve g. Berita gembira hebat, Steve!
Ogre Psalm33
4
nanoTime () tidak menjamin akurasi lebih baik daripada currentTimeMillis, tetapi banyak implementasi JVM yang memiliki akurasi lebih baik dengan nanoTime.
James Schek
5
@JamesSchek Anda benar-benar perlu memperhatikan kata-kata Anda, seperti yang telah saya sebutkan di komentar identik ini di tempat lain; nanoTimedijamin akan setidaknya tegas sebagai currentTimeMillis. docs.oracle.com/javase/7/docs/api/java/lang/…
b1nary.atr0phy
Satu keuntungan kecil dari currentTimeMillisitu adalah timestamp yang sebenarnya, dan dapat digunakan untuk mencatat waktu mulai / akhir juga, sementara nanoTime"hanya dapat digunakan untuk mengukur waktu yang berlalu dan tidak terkait dengan gagasan lain tentang sistem atau waktu jam dinding. . "
Brad Parks
177

Ayolah teman-teman! Tidak ada yang menyebutkan cara Jambu untuk melakukan itu (yang bisa dibilang luar biasa):

import com.google.common.base.Stopwatch;

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

Yang menyenangkan adalah bahwa Stopwatch.toString () melakukan pekerjaan yang baik dalam memilih unit waktu untuk pengukuran. Yaitu jika nilainya kecil, itu akan menghasilkan 38 ns, jika itu panjang, itu akan menunjukkan 5m 3s

Bahkan lebih baik:

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

Catatan: Google Guava membutuhkan Java 1.6+

Dmitry Kalashnikov
sumber
21
Sayangnya, Stopwatch Guava tidak aman. Saya belajar ini dengan cara yang sulit.
Dexter Legaspi
6
@DexterLegaspi Akan sangat tertarik dengan pengalaman Anda! Mau berbagi?
Siddhartha
1
Menggunakan stopwatch secara paralel akan membuat Anda menelepon start()berkali-kali secara berurutan (sama untuk stop()).
Mingwei Samuel
141

Menggunakan Instan dan Durasi dari API baru Java 8,

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

output,

PT5S
Sufiyan Ghori
sumber
2
Terima kasih, Bagaimana saya bisa menampilkan hasilnya tanpa memiliki PT di depan?
java123999
1
Masalah dengan metode adalah bahwa Instant tidak masalah milli dan nano presisi kedua. Ref: stackoverflow.com/questions/20689055/…
prashantsunkari
8
@ java123999: Anda bisa menelepon Duration.between(start, end).getSeconds(). Durationjuga memiliki metode untuk mengkonversi ke unit waktu lainnya, misalnya toMillis()yang mengkonversi ke milidetik.
Emil Lunde
100

Kumpulkan semua cara yang mungkin bersama menjadi satu tempat.

Tanggal

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);

Sistem. 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 ) );

Format yang Dapat Dibaca Manusia

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;
}

Guava: Google Stopwatch JAR «Objek Stopwatch adalah untuk mengukur waktu yang telah berlalu dalam nanodetik.

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 menyediakan API yang nyaman untuk pengaturan waktu.

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 -TIME

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 date time API dari Java 8 «Sebuah objek Durasi mewakili periode waktu antara dua objek Instan .

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 menyediakankelas utilitas StopWatch untuk mengukur waktu yang berlalu di Jawa.

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());
}

Keluaran:

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
sumber
Stopwatch Guava, Apache Commons dan Spring Framework tidak aman untuk thread. Tidak aman untuk penggunaan produksi.
Deepak Puthraya
@DeepakPuthraya lalu perpustakaan mana yang digunakan yang aman untuk penggunaan produksi?
gaurav
1
@DeepakPuthraya Anda dapat menggunakan java 8 yang disediakan Java date time API. Sederhana saja.
Yash
IMO posting ini akan mendapat manfaat jika setiap solusi juga akan menunjukkan output dari sistem keluar.
BAERUS
87

Gunakan profiler (JProfiler, Netbeans Profiler, Visual VM, Eclipse Profiler, dll). Anda akan mendapatkan hasil yang paling akurat dan paling tidak mengganggu. Mereka menggunakan mekanisme JVM bawaan untuk pembuatan profil yang juga dapat memberi Anda informasi tambahan seperti tumpukan jejak, jalur eksekusi, dan hasil yang lebih komprehensif jika perlu.

Ketika menggunakan profiler yang terintegrasi penuh, itu sepele untuk membuat profil suatu metode. Klik kanan, Profiler -> Tambahkan ke Metode Root. Kemudian jalankan profiler seperti Anda melakukan uji coba atau debugger.

James Schek
sumber
Ini juga saran yang bagus, dan salah satu momen bola lampu "duh" bagi saya ketika saya membaca jawaban ini. Proyek kami menggunakan JDeveloper, tetapi saya memeriksa, dan tentu saja, ia punya profiler bawaan!
Ogre Psalm33
2
Dari java 7 build 40 (saya pikir) mereka termasuk mantan Perekam Penerbangan JRockits ke java (mencari Java Mission Control)
Niels Bech Nielsen
Cukup yakin @NielsBechNielsen! oracle.com/technetwork/java/javaseproducts/mission-control/…
Ogre Psalm33
Bagaimana cara mendapatkan eksekusi metode di Java oleh Visual VM, misalnya?
okwap
41

Ini mungkin bukan yang Anda ingin saya katakan, tetapi ini adalah penggunaan yang baik dari AOP. Cambuk pencegat proxy di sekitar metode Anda, dan lakukan penghitungan waktu di sana.

Sayangnya, apa, mengapa, dan bagaimana AOP berada di luar cakupan jawaban ini, tetapi itulah kemungkinan saya melakukannya.

Sunting: Berikut ini tautan ke Spring AOP untuk membantu Anda memulai, jika Anda tertarik. Ini adalah implementasi AOP yang paling mudah diakses yang saya temui untuk java.

Juga, mengingat saran orang lain yang sangat sederhana, saya harus menambahkan bahwa AOP adalah untuk saat Anda tidak ingin hal-hal seperti waktu menginvasi kode Anda. Tetapi dalam banyak kasus, pendekatan sederhana dan mudah semacam itu baik-baik saja.

skaffman
sumber
3
Berikut ini adalah tutorial tentang cara melakukan ini dengan Spring: veerasundar.com/blog/2010/01/…
David Tinker
39

System.currentTimeMillis();BUKAN pendekatan yang bagus untuk mengukur kinerja algoritma Anda. Ini mengukur total waktu yang Anda alami sebagai pengguna menonton layar komputer. Ini termasuk juga waktu yang dihabiskan oleh segala sesuatu yang berjalan di komputer Anda di latar belakang. Ini bisa membuat perbedaan besar jika Anda memiliki banyak program yang berjalan di workstation Anda.

Pendekatan yang tepat menggunakan java.lang.managementpaket.

Dari http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking situs web:

  • "Waktu pengguna" adalah waktu yang dihabiskan untuk menjalankan kode aplikasi Anda sendiri.
  • "Waktu sistem" adalah waktu yang dihabiskan untuk menjalankan kode OS atas nama aplikasi Anda (seperti untuk I / O).

getCpuTime() metode memberi Anda jumlah tersebut:

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
sumber
4
Ini jelas merupakan poin yang baik, bahwa "waktu pengguna" (waktu jam dinding) tidak selalu merupakan ukuran kinerja yang hebat, terutama dalam program multi-utas.
Ogre Psalm33
Inilah jawaban yang saya cari.
ZhaoGang
30

Dengan Java 8 Anda juga dapat melakukan hal seperti ini dengan setiap metode normal :

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

dengan TimeIt seperti:

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;
}
}

Dengan metode ini Anda dapat membuat pengukuran waktu yang mudah di mana saja dalam kode Anda tanpa merusaknya. Dalam contoh sederhana ini saya hanya mencetak waktu. Bolehkah Anda menambahkan Switch for TimeIt, misalnya untuk hanya mencetak waktu di DebugMode atau sesuatu.

Jika Anda bekerja dengan Function, Anda dapat melakukan sesuatu seperti ini:

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
sumber
Ini terlihat jauh lebih baik daripada solusi lain. Lebih dekat ke Spring AOP namun lebih ringan dari itu. Benar java 8 cara! +1 Terima kasih!
Amit Kumar
Mungkin ini terlihat bagus untuk Anda, karena Stefan menggunakan fungsi java baru yang mewah. Tetapi saya pikir ini sulit sekali dibaca dan dimengerti.
Stimpson Cat
18

Kita juga dapat menggunakan kelas StopWatch dari Apache commons untuk mengukur waktu.

Kode sampel

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
sumber
15

Hanya sedikit putaran, jika Anda tidak menggunakan tooling dan ingin menghitung metode waktu dengan waktu eksekusi yang rendah: jalankan berkali-kali, setiap kali menggandakan berapa kali dieksekusi sampai Anda mencapai satu detik, atau lebih. Dengan demikian, waktu Panggilan ke System.nanoTime dan sebagainya, atau keakuratan System.nanoTime tidak banyak mempengaruhi hasilnya.

    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");

Tentu saja, peringatan tentang menggunakan jam dinding berlaku: pengaruh JIT-kompilasi, beberapa thread / proses dll Dengan demikian, Anda harus terlebih dahulu melaksanakan metode yang banyak kali pertama, sehingga compiler JIT melakukan tugasnya, dan kemudian ulangi tes ini beberapa kali dan ambil waktu eksekusi terendah.

Hans-Peter Störr
sumber
13

Kami menggunakan anotasi AspectJ dan Java untuk tujuan ini. Jika kita perlu tahu waktu eksekusi untuk suatu metode, kita beri penjelasan sederhana. Versi yang lebih maju dapat menggunakan level log sendiri yang dapat diaktifkan dan dinonaktifkan saat runtime.

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;
  }
  [...]
}

sumber
13

JEP 230: Microbenchmark Suite

FYI, JEP 230: Microbenchmark Suite adalah proyek OpenJDK untuk:

Tambahkan seperangkat dasar microbenchmarks ke kode sumber JDK, dan membuatnya mudah bagi pengembang untuk menjalankan microbenchmarks yang ada dan membuat yang baru.

Fitur ini tiba di Java 12 .

Java Microbenchmark Harness (JMH)

Untuk versi Java yang lebih lama, lihatlah proyek Java Microbenchmark Harness (JMH) yang menjadi dasar JEP 230.

Basil Bourque
sumber
11

Kode yang sangat bagus.

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;
  }
gunung es
sumber
3
Sebenarnya pertanyaannya adalah bagaimana menghitung jumlah waktu yang dibutuhkan suatu metode, bukan bagaimana memformatnya. Namun pertanyaan ini sudah cukup lama (hampir empat tahun!). Cobalah untuk menghindari membangkitkan kembali utas lama kecuali jika tanggapan akan menambahkan sesuatu yang baru dan signifikan atas tanggapan yang ada.
Leigh
1
Dan untuk menambahkan mili yang tersisa ke akhir, buat perubahan berikut: 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

Anda dapat menggunakan Perf4j . Utilitas yang sangat keren. Penggunaannya sederhana

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; 
}

Informasi lebih lanjut dapat ditemukan di Panduan Pengembang

Sunting: Proyek sepertinya mati

mergenchik
sumber
1
Perf4j juga dapat menghasilkan statistik yang bagus .
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
sumber
1
Roll kelas sederhana Anda sendiri adalah pilihan yang baik ketika Anda sudah memiliki sistem build dan pengaturan OTS tergantung, dan tidak ingin repot-repot menarik paket OTS lain yang mencakup kelas timer utilitas.
Ogre Psalm33
7

Saya pada dasarnya melakukan variasi ini, tetapi mempertimbangkan bagaimana kompilasi hotspot bekerja, jika Anda ingin mendapatkan hasil yang akurat, Anda perlu membuang beberapa pengukuran pertama dan pastikan Anda menggunakan metode ini dalam aplikasi dunia nyata (baca aplikasi khusus).

Jika JIT memutuskan untuk mengompilasinya, angka Anda akan sangat bervariasi. jadi sadar saja

Lukas
sumber
7

Menggunakan AOP / AspectJ dan @Loggableanotasi dari jcabi-aspek Anda dapat melakukannya dengan mudah dan ringkas:

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

Setiap panggilan ke metode ini akan dikirim ke fasilitas logging SLF4J dengan DEBUGtingkat logging. Dan setiap pesan log akan menyertakan waktu eksekusi.

yegor256
sumber
7

Spring menyediakan kelas utilitas org.springframework.util.StopWatch , sesuai JavaDoc :

Stopwatch sederhana, memungkinkan penentuan waktu sejumlah tugas, mengekspos total waktu berjalan dan waktu berjalan untuk setiap tugas yang disebutkan.

Pemakaian:

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());

Keluaran:

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

Dengan Aspek:

@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
sumber
Apakah mungkin menggunakan ini dengan AspectJ?
zygimantus
7

Saya telah menulis metode untuk mencetak waktu eksekusi metode dalam bentuk yang mudah dibaca. Misalnya, untuk menghitung faktorial 1 Juta, dibutuhkan sekitar 9 menit. Jadi waktu eksekusi dapat dicetak sebagai:

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

Kode di sini:

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
sumber
6

Ada beberapa cara untuk melakukan itu. Saya biasanya kembali menggunakan sesuatu seperti ini:

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

atau hal yang sama dengan System.nanoTime ();

Untuk sesuatu yang lebih pada sisi pembandingan, tampaknya juga ada yang ini: http://jetm.void.fm/ Tidak pernah mencobanya.

Horst Gutmann
sumber
6

Anda dapat menggunakan perpustakaan Metrik yang menyediakan berbagai alat ukur. Tambahkan ketergantungan:

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

Dan konfigurasikan untuk lingkungan Anda.

Metode dapat dijelaskan dengan @Timed :

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

atau sepotong kode yang dibungkus dengan Timer :

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

Metrik gabungan dapat diekspor ke konsol, JMX, CSV, atau lainnya.

@Timed contoh keluaran metrik:

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
Justas
sumber
5

Jika Anda ingin waktu jam dinding

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

Seperti yang dikatakan "skaffman", gunakan AOP ATAU Anda dapat menggunakan tenunan bytecode run time, seperti halnya alat cakupan metode pengujian unit yang digunakan untuk secara transparan menambahkan info waktu ke metode yang digunakan.

Anda dapat melihat kode yang digunakan oleh alat alat sumber terbuka seperti Emma ( http://downloads.sourceforge.net/emma/emma-2.0.5312-src.zip?modtime=1118607545&big_mirror=0 ). Alat jangkauan opensource lainnya adalah http://prdownloads.sourceforge.net/cobertura/cobertura-1.9-src.zip?download .

Jika Anda akhirnya berhasil melakukan apa yang Anda tetapkan, mohon. bagikan kembali dengan komunitas di sini dengan tugas / toples semut Anda.

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

Saya mengubah kode dari jawaban yang benar untuk mendapatkan hasil dalam hitungan detik:

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
sumber
4

Anda dapat menggunakan kelas stopwatch dari proyek pegas inti:

Kode:

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

Dokumentasi untuk Stopwatch: sederhana, memungkinkan penentuan waktu sejumlah tugas, mengekspos total waktu berjalan dan waktu berjalan untuk setiap tugas yang disebutkan. Menyembunyikan penggunaan System.currentTimeMillis (), meningkatkan keterbacaan kode aplikasi dan mengurangi kemungkinan kesalahan perhitungan. Perhatikan bahwa objek ini tidak dirancang untuk aman-utas dan tidak menggunakan sinkronisasi. Kelas ini biasanya digunakan untuk memverifikasi kinerja selama pembuktian konsep dan dalam pengembangan, bukan sebagai bagian dari aplikasi produksi.

Praveen Jain
sumber
3

Anda dapat mencoba cara ini jika hanya ingin tahu waktu.

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

Ok, ini adalah kelas sederhana untuk digunakan untuk pengaturan waktu sederhana dari fungsi Anda. Ada contoh di bawahnya.

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");
    }
}

Contoh penggunaan:

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;
}

Contoh output konsol:

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

Di Java 8 kelas baru bernama Instantdiperkenalkan. Sesuai dok:

Instan mewakili awal nanodetik pada garis waktu. Kelas ini berguna untuk menghasilkan cap waktu untuk mewakili waktu alat berat. Kisaran instan membutuhkan penyimpanan nomor yang lebih besar daripada panjang. Untuk mencapai ini, kelas menyimpan lama mewakili epoch-detik dan int mewakili nanodetik, yang akan selalu antara 0 dan 999.999.999. Zaman-detik diukur dari zaman Jawa standar 1970-01-01T00: 00: 00Z di mana instants setelah epoch memiliki nilai positif, dan instants sebelumnya memiliki nilai negatif. Untuk bagian epos-detik dan nanodetik, nilai yang lebih besar selalu lebih lambat daripada nilai yang lebih kecil.

Ini dapat digunakan sebagai:

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

Mencetak PT7.001S.

akhil_mittal
sumber