ฉันจะจับเวลาการเรียกใช้เมธอดใน Java ได้อย่างไร


834
  1. ฉันจะรับเวลาดำเนินการของวิธีได้อย่างไร
  2. มีTimerคลาสยูทิลิตี้สำหรับสิ่งต่าง ๆ เช่นเวลาที่ต้องใช้เวลานานหรือไม่?

การค้นหาส่วนใหญ่ใน Google ส่งคืนผลลัพธ์สำหรับตัวจับเวลาที่กำหนดหัวข้อและงานซึ่งไม่ใช่สิ่งที่ฉันต้องการ


JAMon API เป็นฟรี Java API ที่ปลอดภัยง่ายและมีประสิทธิภาพสูงซึ่งช่วยให้นักพัฒนาสามารถตรวจสอบประสิทธิภาพและความยืดหยุ่นของแอปพลิเคชันการผลิต JAMon ติดตามจำนวนการเข้าชมเวลาดำเนินการ (รวม, เฉลี่ย, min, max, std dev) และอื่น ๆ http://jamonapi.sourceforge.net/ดาวน์โหลด: http://sourceforge.net/project/showfiles.php?group_id=96550
Mike Pone

1
คุณอาจต้องการดูคลาสApache Commons Lang StopWatch คลาสยูทิลิตี้ที่เรียบง่าย แต่มีประโยชน์


ใช่ StopWatch เหมาะสำหรับสิ่งนี้
Shubham Pandey

Java 8 ใช้Instantคลาส: stackoverflow.com/a/30975902/1216775
akhil_mittal

คำตอบ:


1207

มีวิธีที่ล้าสมัยอยู่เสมอ:

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

long duration = (endTime - startTime);  //divide by 1000000 to get milliseconds.

233
ที่จริงแล้วมันเป็น "new-fashioned" เพราะคุณใช้ nanoTime ซึ่งไม่ได้เพิ่มจนกระทั่ง java5
John Gardner

11
(หรือการใช้ System.currentTimeMillis ()) นี้ดูเหมือนจะเป็นวิธีที่มักจะทำใน Java ... ที่ฉันเคยเห็นแล้ว มันยังทำให้ฉันประหลาดใจเล็กน้อยว่าไม่มีคลาสบิวท์อินที่สวยงามเช่น Timer t = new Timer (); String s = t.getElapsed (รูปแบบ); ฯลฯ ...
Ogre Psalm33

18
nanoTime ไม่รับประกันความถูกต้องดีกว่า currentTimeMillis () ถึงแม้ว่ามันมักจะทำก็ตาม forums.sun.com/thread.jspa?messageID=9460663และsimongbrown.com/blog/2007/08/20//
James

10
แน่นอนว่าเป็นเรื่องสำคัญที่จะต้องจำข้อผิดพลาดของการวัดขนาดเล็กเช่นการเพิ่มประสิทธิภาพของคอมไพเลอร์ / JVM ที่อาจบิดเบือนผลลัพธ์ = 8-)
Yuval

18
ไม่จำเป็นต้องมีการบล็อกในที่สุดเนื่องจากจะไม่ใช้ endTime หากมีข้อผิดพลาดเกิดขึ้น
Peter Lawrey

197

ฉันไปกับคำตอบง่ายๆ ได้ผลสำหรับฉัน

long startTime = System.currentTimeMillis();

doReallyLongThing();

long endTime = System.currentTimeMillis();

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

มันใช้งานได้ค่อนข้างดี ความละเอียดชัดเป็นเพียงมิลลิวินาทีเท่านั้นคุณสามารถทำได้ดีกว่าด้วย System.nanoTime () มีข้อ จำกัด บางอย่างสำหรับทั้งสอง (ตัวแบ่งกำหนดการของระบบปฏิบัติการ ฯลฯ ) แต่วิธีนี้ใช้ได้ค่อนข้างดี

ค่าเฉลี่ยในการวิ่งสองรอบ (ยิ่งดี) และคุณจะได้รับความคิดที่ดี


51
ที่จริงแล้ว System.currentTimeMillis () นั้นมีความแม่นยำสูงกว่า 15ms เท่านั้น สำหรับค่าต่ำจริง ๆ ไม่สามารถเชื่อถือได้ วิธีแก้ปัญหาสำหรับเรื่องนี้ (ดังที่กล่าวไว้) คือ System.nanoTime ();
Steve g

ตกลงฉันกำลังจะยอมรับสิ่งนี้เป็นคำตอบอย่างเป็นทางการจนกว่าฉันจะอ่านความคิดเห็นของสตีฟจี อาหารอันโอชะที่ดีสตีฟ!
Ogre Psalm33

4
nanoTime () ไม่รับประกันความถูกต้องดีกว่า currentTimeMillis แต่การใช้ JVM จำนวนมากมีความแม่นยำที่ดีขึ้นเมื่อใช้ nanoTime
James Schek

5
@JamesSchek คุณต้องดูถ้อยคำของคุณจริงๆเพราะฉันได้พูดถึงความคิดเห็นที่เหมือนกันนี้แล้วที่อื่น; nanoTimeรับประกันได้ว่าจะอย่างน้อยเป็นอย่างเด็ดเดี่ยวcurrentTimeMillisเป็น docs.oracle.com/javase/7/docs/api/java/lang/…
b1nary.atr0phy

ข้อได้เปรียบเล็กน้อยอย่างหนึ่งcurrentTimeMillisคือมันเป็นเวลาที่แท้จริงและสามารถใช้ในการบันทึกเวลาเริ่มต้น / สิ้นสุดได้เช่นกันในขณะที่nanoTime"สามารถใช้เพื่อวัดเวลาที่ผ่านไปและไม่เกี่ยวข้องกับความคิดอื่น ๆ ของระบบหรือเวลานาฬิกา ."
Brad Parks

177

มากับพวก! ไม่มีใครพูดถึงวิธีการทำฝรั่ง (ซึ่งน่ากลัวมาก):

import com.google.common.base.Stopwatch;

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

สิ่งที่ดีคือ Stopwatch.toString () ทำงานได้ดีในการเลือกหน่วยเวลาสำหรับการวัด นั่นคือถ้าค่ามีขนาดเล็กมันจะออกมา 38 ns ถ้ามันยาวมันจะแสดง 5m 3s

ยิ่งดีกว่า:

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

หมายเหตุ: Google Guava ต้องการ Java 1.6+


21
น่าเสียดายที่นาฬิกาจับเวลาของ Guava ไม่ปลอดภัยสำหรับเธรด ฉันเรียนรู้วิธีนี้ยาก
Dexter Legaspi

6
@DexterLegaspi จะสนใจประสบการณ์ของคุณมาก! สนใจที่จะแบ่งปัน?
Siddhartha

1
การใช้นาฬิกาจับเวลาแบบขนานจะทำให้คุณโทรติดต่อกันstart()หลายครั้ง (เหมือนกันstop())
Mingwei ซามูเอล

141

ใช้InstantและDurationจาก API ใหม่ของ Java 8

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

เอาท์พุท

PT5S

2
ขอบคุณฉันจะส่งออกผลลัพธ์โดยไม่ต้องมี PT อยู่ข้างหน้าได้อย่างไร
java123999

1
ปัญหาเกี่ยวกับวิธีการคือ Instant นั้นไม่ได้มีปัญหาความแม่นยำที่สองเป็นพันและนาโน Ref: stackoverflow.com/questions/20689055/…
prashantsunkari

8
@ java123999: คุณสามารถโทรDuration.between(start, end).getSeconds()ได้ Durationยังมีวิธีการแปลงเป็นหน่วยเวลาอื่น ๆ เช่นtoMillis()ซึ่งแปลงเป็นมิลลิวินาที
Emil Lunde

100

รวบรวมวิธีที่เป็นไปได้ทั้งหมดไว้ด้วยกันในที่เดียว

วันที่

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

ระบบ. 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 ) );

รูปแบบที่มนุษย์อ่านได้

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 «วัตถุของนาฬิกาจับเวลาคือการวัดเวลาที่ผ่านไปในหน่วยนาโนวินาที

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ให้ API ที่สะดวกสำหรับการกำหนดเวลา

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 -เวลา

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 จาก Java 8 « วัตถุระยะเวลาแสดงช่วงเวลาระหว่างวัตถุทันทีสองรายการ

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จัดเตรียมคลาสยูทิลิตี้ StopWatchเพื่อวัดเวลาที่ผ่านไปใน 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());
}

เอาท์พุท:

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]

นาฬิกาจับเวลาของ Guava, Apache Commons และ Spring Framework ไม่ปลอดภัยสำหรับเธรด ไม่ปลอดภัยสำหรับการใช้งานจริง
Deepak Puthraya

@DeepakPuthraya ห้องสมุดใดที่จะใช้ซึ่งปลอดภัยสำหรับการใช้งานจริงหรือไม่
gaurav

1
@DeepakPuthraya คุณสามารถใช้ Java 8 ที่ให้ Java วันเวลา API ซึ่งง่าย
Yash

IMO โพสต์นี้จะได้รับประโยชน์หากทุกโซลูชันจะแสดงผลลัพธ์ของระบบด้วย
BAERUS

87

ใช้ profiler (JProfiler, Netbeans Profiler, Visual VM, Eclipse Profiler ฯลฯ ) คุณจะได้ผลลัพธ์ที่ถูกต้องที่สุดและเป็นสิ่งที่รบกวนน้อยที่สุด พวกเขาใช้กลไก JVM ในตัวสำหรับการทำโปรไฟล์ซึ่งสามารถให้ข้อมูลเพิ่มเติมเช่นการติดตามสแต็กพา ธ การเรียกใช้งานและผลลัพธ์ที่ครอบคลุมมากขึ้นหากจำเป็น

เมื่อใช้ profiler แบบครบวงจรมันเป็นเรื่องเล็กน้อยที่จะสร้างโปรไฟล์วิธี คลิกขวา Profiler -> เพิ่มไปยังวิธีการรูท จากนั้นเรียกใช้ตัวสร้างโปรไฟล์เช่นเดียวกับที่คุณทำการทดสอบหรือดีบักเกอร์


นี่เป็นคำแนะนำที่ยอดเยี่ยมและหนึ่งในนั้นคือ "duh" ช่วงเวลาแสงไฟสำหรับฉันเมื่อฉันอ่านคำตอบนี้ โครงการของเราใช้ JDeveloper แต่ฉันตรวจสอบแล้วและแน่นอนว่ามันมี profiler ในตัว!
Ogre Psalm33

2
จาก java 7 build 40 (ฉันคิดว่า) พวกเขาได้รวม JRockits Flight Recorder ตัวเก่ามาเป็นจาวา (ค้นหา Java Mission Control)
Niels Bech Nielsen


วิธีการรับการดำเนินการวิธีการใน Java โดย Visual VM เช่น?
okwap

41

นี่อาจไม่ใช่สิ่งที่คุณต้องการให้ฉันพูด แต่นี่เป็นการใช้ AOP ได้ดี ชัก interceptor พร็อกซี่รอบวิธีการของคุณและทำเวลาในการมี

อะไรคือสาเหตุและวิธีการของ AOP นั้นค่อนข้างจะเกินขอบเขตของคำตอบนี้น่าเศร้า แต่นั่นก็เป็นสิ่งที่ฉันควรทำ

แก้ไข: นี่คือลิงค์ไปสู่ ​​Spring AOP เพื่อให้คุณเริ่มต้นถ้าคุณกระตือรือร้น นี่เป็นการใช้งาน AOP ที่เข้าถึงได้ง่ายที่สุดสำหรับ Iive

นอกจากนี้เมื่อพิจารณาจากคำแนะนำง่ายๆของคนอื่นฉันควรเพิ่มว่า AOP ใช้เมื่อคุณไม่ต้องการให้เวลาบุกรุกรหัสของคุณ แต่ในหลาย ๆ กรณีวิธีการที่ง่ายและสะดวกนั้นก็ใช้ได้


3
นี่คือการสอนเกี่ยวกับวิธีการทำเช่นนี้กับ Spring: veerasundar.com/blog/2010/01/…
David Tinker

39

System.currentTimeMillis();ไม่ใช่วิธีที่ดีในการวัดประสิทธิภาพของอัลกอริทึมของคุณ มันวัดเวลารวมที่คุณพบในฐานะผู้ใช้ที่ดูหน้าจอคอมพิวเตอร์ ซึ่งรวมถึงเวลาที่ทุกสิ่งทุกอย่างทำงานบนคอมพิวเตอร์ของคุณซึ่งทำงานอยู่เบื้องหลัง สิ่งนี้อาจสร้างความแตกต่างอย่างมากในกรณีที่คุณมีโปรแกรมมากมายที่ทำงานอยู่บนเวิร์กสเตชันของคุณ

วิธีการที่เหมาะสมคือใช้java.lang.managementแพ็คเกจ

จากhttp://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarkingเว็บไซต์:

  • "เวลาของผู้ใช้" คือเวลาที่ใช้เรียกใช้รหัสของแอปพลิเคชันของคุณ
  • "เวลาของระบบ" คือเวลาที่ใช้ในการเรียกใช้รหัส OS ในนามของแอปพลิเคชันของคุณ (เช่นสำหรับ I / O)

getCpuTime() วิธีการให้ผลรวมของเหล่านั้น:

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

}

4
นี่เป็นจุดที่ดีอย่างแน่นอนว่า "เวลาผู้ใช้" (เวลานาฬิกาแขวน) ไม่ได้เป็นเครื่องวัดประสิทธิภาพที่ดีเสมอไปโดยเฉพาะอย่างยิ่งในโปรแกรมแบบมัลติเธรด
Ogre Psalm33

นี่คือคำตอบที่ฉันกำลังมองหา
ZhaoGang

30

ด้วย Java 8 คุณสามารถทำสิ่งนี้ได้ทุกวิธีปกติ:

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

ด้วย TimeIt เช่น:

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

ด้วย methode นี้คุณสามารถทำการวัดเวลาได้อย่างง่ายดายทุกที่ในรหัสของคุณโดยไม่ทำให้มันแตก ในตัวอย่างง่ายๆนี้ฉันเพิ่งพิมพ์เวลา ขอให้คุณเพิ่มสวิตช์สำหรับ TimeIt เช่นเพื่อพิมพ์เฉพาะเวลาใน DebugMode หรือบางอย่าง

หากคุณกำลังทำงานกับฟังก์ชั่นคุณสามารถทำบางสิ่งเช่นนี้:

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

มันดูดีกว่าโซลูชันอื่น ๆ มันใกล้กับสปริง AOP แต่ก็เบากว่านั้น True java 8 way! +1 ขอบคุณ!
Amit Kumar

บางทีนี่อาจจะดูดีสำหรับคุณเพราะ Stefan ใช้ฟังก์ชั่นจาวาแฟนซีแนวใหม่ แต่ฉันคิดว่ามันยากที่จะอ่านและเข้าใจยาก
Stimpson Cat

18

นอกจากนี้เรายังสามารถใช้คลาส StopWatch ของ Apache สามัญเพื่อวัดเวลา

โค้ดตัวอย่าง

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

15

เพียงแค่บิดเล็กน้อยหากคุณไม่ได้ใช้เครื่องมือและต้องการใช้วิธีการเวลาที่มีเวลาดำเนินการต่ำ: ดำเนินการหลายครั้งในแต่ละครั้งที่เพิ่มจำนวนเป็นสองเท่าของเวลาที่จะดำเนินการจนกว่าคุณจะถึงหนึ่งวินาทีหรือมากกว่านั้น ดังนั้นเวลาของการเรียกไปที่ System.nanoTime และอื่น ๆ หรือความแม่นยำของ System.nanoTime จะส่งผลต่อผลลัพธ์มากน้อยเพียงใด

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

แน่นอนว่าคำเตือนเกี่ยวกับการใช้นาฬิกาแขวนมีผลกับการรวบรวม JIT, หลายเธรด / กระบวนการ ฯลฯ ดังนั้นคุณต้องดำเนินการวิธีการก่อนหลายครั้งก่อนเช่นคอมไพเลอร์ JIT ทำงานและจากนั้น ทำซ้ำการทดสอบนี้หลายครั้งและใช้เวลาดำเนินการต่ำที่สุด


13

เรากำลังใช้คำอธิบายประกอบ AspectJ และ Java เพื่อจุดประสงค์นี้ หากเราต้องการทราบเวลาในการดำเนินการของเมธอดเราจะอธิบายให้ง่าย เวอร์ชันขั้นสูงสามารถใช้ระดับการบันทึกของตนเองที่สามารถเปิดใช้งานและปิดการใช้งานในขณะใช้งานจริง

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

13

JEP 230: Microbenchmark Suite

FYI, JEP 230: Microbenchmark Suiteเป็นโครงการOpenJDKเพื่อ:

เพิ่มชุดพื้นฐานของ microbenchmarks ในซอร์สโค้ด JDK และทำให้ง่ายสำหรับนักพัฒนาในการเรียกใช้ microbenchmarks ที่มีอยู่และสร้างใหม่

คุณลักษณะนี้จะมาถึงในJava 12

Java Microbenchmark Harness (JMH)

สำหรับ Java เวอร์ชันก่อนหน้าดูที่โครงการJava Microbenchmark Harness (JMH)ที่ใช้ JEP 230


11

รหัสที่ดีจริงๆ

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

3
ที่จริงคำถามคือวิธีการคำนวณระยะเวลาที่ใช้วิธีไม่ใช่วิธีการจัดรูปแบบ อย่างไรก็ตามคำถามนี้ค่อนข้างเก่า (เกือบสี่ปี!) พยายามหลีกเลี่ยงการสร้างเธรดเก่าอีกครั้งเว้นแต่ว่าการตอบกลับจะเพิ่มสิ่งใหม่และสำคัญกว่าการตอบกลับที่มีอยู่
Leigh

1
และเพื่อเพิ่ม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); }
มิลลิวินาที

10

คุณสามารถใช้Perf4j ยูทิลิตี้ที่ยอดเยี่ยมมาก การใช้งานง่าย

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

ข้อมูลเพิ่มเติมสามารถพบได้ในคู่มือนักพัฒนาซอฟต์แวร์

แก้ไข: โครงการดูเหมือนจะตาย


1
Perf4j ยังสามารถสร้างความสุขสถิติ
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()));
    }

}

1
ม้วนคลาสที่เรียบง่ายของคุณเองเป็นทางเลือกที่ดีเมื่อคุณมีระบบการสร้างและติดตั้ง OTS แบบพึ่งพาแล้วและไม่ต้องการรบกวนการดึงในแพ็คเกจ OTS อื่นที่มีคลาสตัวจับเวลายูทิลิตี้
Ogre Psalm33

7

โดยทั่วไปฉันจะทำสิ่งต่าง ๆ นี้ แต่พิจารณาว่าการรวบรวมฮอตสปอตทำงานอย่างไรถ้าคุณต้องการได้ผลลัพธ์ที่ถูกต้องคุณต้องทำการวัดสองสามครั้งแรกและตรวจสอบให้แน่ใจว่าคุณกำลังใช้วิธีในโลกแห่งความเป็นจริง (อ่านเฉพาะแอปพลิเคชัน)

หาก JIT ตัดสินใจรวบรวมตัวเลขของคุณจะแตกต่างกันอย่างมาก ดังนั้นจงระวัง


7

การใช้ AOP / AspectJ และ@Loggableหมายเหตุประกอบจากjcabi-problemsคุณสามารถทำได้ง่ายและกะทัดรัด:

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

การเรียกใช้วิธีนี้ทุกครั้งจะถูกส่งไปยังระบบบันทึกการทำงาน SLF4J พร้อมDEBUGระดับการบันทึก และทุกข้อความบันทึกจะมีเวลาดำเนินการ


7

Spring จัดเตรียมยูทิลิตี้คลาส org.springframework.util.StopWatchตาม JavaDoc:

นาฬิกาจับเวลาแบบง่ายช่วยให้สามารถกำหนดเวลาของงานจำนวนหนึ่งเปิดเผยเวลาทำงานทั้งหมดและเวลาทำงานสำหรับแต่ละงานที่มีชื่อ

การใช้งาน:

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

เอาท์พุท:

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

ด้วยมุมมอง:

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

เป็นไปได้ไหมที่จะใช้สิ่งนี้กับ AspectJ?
zygimantus

7

ฉันได้เขียนวิธีการที่จะพิมพ์เวลาดำเนินการของวิธีการในรูปแบบที่อ่านได้มาก ตัวอย่างเช่นในการคำนวณแฟคทอเรียลที่ 1 ล้านจะใช้เวลาประมาณ 9 นาที ดังนั้นเวลาดำเนินการจะถูกพิมพ์เป็น:

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

รหัสอยู่ที่นี่:

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

6

มีสองวิธีในการทำเช่นนั้น ปกติแล้วฉันจะกลับไปใช้สิ่งนี้:

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

หรือสิ่งเดียวกันกับ System.nanoTime ();

สำหรับบางสิ่งที่เพิ่มเติมเกี่ยวกับการเปรียบเทียบของสิ่งต่าง ๆ ดูเหมือนจะเป็นสิ่งนี้: http://jetm.void.fm/ไม่เคยลองเลย


6

คุณสามารถใช้ห้องสมุดMetricsซึ่งมีเครื่องมือวัดต่างๆ เพิ่มการพึ่งพา:

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

และกำหนดค่าให้กับสภาพแวดล้อมของคุณ

วิธีการสามารถเพิ่มความคิดเห็นด้วย@Timed :

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

หรือชิ้นส่วนของรหัสห่อด้วยตัวจับเวลา :

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

ตัวชี้วัดโดยรวมสามารถส่งออกไปยังคอนโซล, JMX, CSV หรืออื่น ๆ

@Timed ตัวอย่างเอาต์พุตเมทริก:

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

5

หากคุณต้องการเวลานาฬิกาแขวน

long start_time = System.currentTimeMillis();
object.method();
long end_time = System.currentTimeMillis();
long execution_time = end_time - start_time;

5

ดังที่คำสั่ง "skaffman" ใช้ AOP หรือคุณสามารถใช้การประมวลผลแบบไบต์ไทม์ของการทอเช่นเดียวกับเครื่องมือครอบคลุมวิธีการทดสอบหน่วยที่ใช้ในการเพิ่มข้อมูลเวลาให้กับวิธีที่เรียกใช้อย่างโปร่งใส

คุณสามารถดูรหัสที่ใช้โดยเครื่องมือเครื่องมือโอเพนซอร์ซเช่น Emma ( http://downloads.sourceforge.net/emma/emma-2.0.5312-src.zip?modtime=1118607545&big_mirror=0 ) เครื่องมือครอบคลุม opensource อื่น ๆ คือhttp://prdownloads.sourceforge.net/cobertura/cobertura-1.9-src.zip?download http://prdownloads.sourceforge.net/cobertura/cobertura-1.9-src.zip?download

หากคุณสามารถทำสิ่งที่คุณต้องการได้ในที่สุด แบ่งปันกลับกับชุมชนที่นี่ด้วยภารกิจ / ขวดของคุณ


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

4

ฉันแก้ไขโค้ดจากคำตอบที่ถูกต้องเพื่อให้ได้ผลลัพธ์ในไม่กี่วินาที:

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

4

คุณสามารถใช้คลาสนาฬิกาจับเวลาจากโครงการแกนกลางของสปริง:

รหัส:

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

เอกสารประกอบสำหรับนาฬิกาจับเวลา: นาฬิกาจับเวลา แบบง่ายช่วยให้สามารถกำหนดเวลาของงานจำนวนมากเปิดเผยเวลาทำงานทั้งหมดและเวลาทำงานสำหรับแต่ละงานที่มีชื่อ ปกปิดการใช้ System.currentTimeMillis () ปรับปรุงการอ่านรหัสแอปพลิเคชันและลดโอกาสในการเกิดข้อผิดพลาดในการคำนวณ โปรดทราบว่าวัตถุนี้ไม่ได้รับการออกแบบให้ปลอดภัยต่อเธรดและไม่ได้ใช้การซิงโครไนซ์ คลาสนี้โดยปกติจะใช้เพื่อตรวจสอบประสิทธิภาพในระหว่างการพิสูจน์แนวคิดและในการพัฒนาแทนที่จะเป็นส่วนหนึ่งของแอปพลิเคชันการผลิต


3

คุณสามารถลองด้วยวิธีนี้หากต้องการทราบเวลา

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

3

ตกลงนี่เป็นคลาสแบบง่าย ๆ ที่จะใช้สำหรับช่วงเวลาแบบง่าย ๆ ของฟังก์ชั่นของคุณ มีตัวอย่างด้านล่าง

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

ตัวอย่างการใช้งาน:

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

ตัวอย่างของเอาต์พุตคอนโซล:

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

3

ใน Java 8 คลาสใหม่ที่ชื่อว่าInstantถูกนำมาใช้ ตามเอกสาร:

แสดงให้เห็นถึงการเริ่มต้นของเสี้ยววินาทีบนเส้นเวลาทันที คลาสนี้มีประโยชน์สำหรับการสร้างการประทับเวลาเพื่อแสดงเวลาของเครื่อง ช่วงของการโต้ตอบแบบทันทีจำเป็นต้องมีการจัดเก็บจำนวนที่มากกว่าความยาว เพื่อให้บรรลุสิ่งนี้คลาสจะทำการจัดเก็บแบบ epoch-seconds และ int ที่แทน nanosecond-of-second ซึ่งจะอยู่ระหว่าง 0 ถึง 999,999,999 ยุควินาทีถูกวัดจากยุค Java มาตรฐานของ 1970-01-01T00: 00: 00Z โดยที่ instants หลังจากยุคนั้นมีค่าเป็นบวกและ instants ก่อนหน้านี้มีค่าลบ สำหรับทั้งยุควินาทีและส่วนนาโนวินาทีค่าที่ใหญ่กว่าจะตามมาในเส้นเวลาเสมอกว่าค่าที่เล็กกว่า

สามารถใช้เป็น:

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

PT7.001Sมันพิมพ์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.