Cách tính thời gian tốc độ thực thi chương trình Java


85

Bạn tính thời gian thực thi chương trình java như thế nào? Tôi không chắc mình nên sử dụng lớp nào để thực hiện việc này.

Tôi đang tìm kiếm một cái gì đó như:

// Some timer starts here
for (int i = 0; i < length; i++) {
  // Do something
}
// End timer here

System.out.println("Total execution time: " + totalExecutionTime);

Câu trả lời:


139
final long startTime = System.currentTimeMillis();
for (int i = 0; i < length; i++) {
  // Do something
}
final long endTime = System.currentTimeMillis();

System.out.println("Total execution time: " + (endTime - startTime));

2
nó thực sự nên nanoTime thực
Eugene

6
Không nên là nanoTime. Xem câu trả lời của rhu.
fabspro

4
Có lý do cụ thể nào mà bạn sử dụng "cuối cùng" ở đây không? Điều gì sẽ khác nếu bạn bỏ từ khóa đó?
dijxtra

9
Việc sử dụng @dijxtra finalcó lợi thế là bạn không thể vô tình gán cho nó (cũng như các lợi thế khác, chẳng hạn như quyền truy cập lớp ẩn danh, v.v.). Trong mã này, nó sẽ không tạo ra sự khác biệt. Đó là một thực tế khá phổ biến để làm tất cả mọi thứ finalvà chỉ mở finalnó ra nếu bạn cần.
tiền ký quỹ

1
Mã được kiểm tra, cùng với các phép đo thời gian, phải được chạy nhiều lần và kết quả đầu tiên nên được loại bỏ. Đầu tiên có thể sẽ bao gồm thời gian tải lớp, v.v. Bằng cách chạy nó nhiều lần, tất nhiên bạn sẽ nhận được mức trung bình hữu ích và đáng tin cậy hơn.
Arun Ramakrishnan

34

Lưu ý rằng có một số vấn đề System#nanoTime()không thể được sử dụng một cách đáng tin cậy trên CPU đa lõi để ghi lại thời gian đã trôi qua ... mỗi lõi có duy trì TSC ( Bộ đếm dấu thời gian ) riêng của mình : bộ đếm này được sử dụng để lấy thời gian nano (thực sự là như vậy số tick kể từ khi CPU khởi động).

Do đó, trừ khi hệ điều hành thực hiện một số công cụ làm cong thời gian TSC để giữ cho các lõi được đồng bộ hóa, thì nếu một luồng được lập lịch trên một lõi khi đọc thời gian ban đầu, sau đó chuyển sang một lõi khác, thời gian tương đối thường có thể nhảy ngược lại và chuyển tiếp.

Tôi đã quan sát điều này một thời gian trước đây trên AMD / Solaris, nơi thời gian trôi qua giữa hai điểm thời gian đôi khi quay trở lại dưới dạng giá trị âm hoặc số dương lớn bất ngờ. Có một bản vá nhân Solaris và một thiết lập BIOS cần thiết để buộc AMD PowerNow! tắt, dường như đã giải quyết nó.

Ngoài ra, có (AFAIK) một lỗi chưa được sửa cho đến nay khi sử dụng java System#nanoTime()trong môi trường VirtualBox; gây ra tất cả các loại vấn đề phân luồng gián đoạn kỳ lạ cho chúng tôi vì phần lớn java.util.concurrencygói dựa trên thời gian nano.

Xem thêm:

System.nanoTime () có hoàn toàn vô dụng không? http://vbox.innotek.de/pipermail/vbox-trac/2010-January/135631.html


9

Bạn nhận được thời gian hệ thống hiện tại, tính bằng mili giây:

final long startTime = System.currentTimeMillis();

Sau đó, bạn làm những gì bạn sẽ làm:

for (int i = 0; i < length; i++) {
  // Do something
}

Sau đó, bạn thấy nó mất bao lâu:

final long elapsedTimeMillis = System.currentTimeMillis() - startTime;

Câu trả lời của BalusC cũng đúng; nó phụ thuộc vào độ phân giải bộ đếm thời gian cần thiết và lý do bạn cần thời gian.
Jonathan Feinberg

9

Bạn có thể tận dụng System#nanoTime(). Nhận nó trước và sau khi thực hiện và chỉ cần thực hiện phép toán. Nó được ưu tiên ở trên System#currentTimeMillis()vì nó có độ chính xác tốt hơn. Tùy thuộc vào phần cứng và nền tảng được sử dụng, nếu không, bạn có thể nhận được khoảng cách không chính xác trong thời gian đã trôi qua. Ở đây với Core2Duo trên Windows, khoảng từ 0 đến ~ 15ms thực sự không thể tính được.

Một công cụ tiên tiến hơn là một hồ sơ .


Bộ hẹn giờ trên Windows không có độ phân giải đặc biệt tốt theo mặc định. Cũng một bộ đếm thời gian hiệu suất cao, nhưng nó khó sử dụng hơn nhiều ngay cả khi từ C và Java không (AFAIK) cung cấp quyền truy cập vào mức độ tấn công thấp đó mà không có JNI.
Donal Fellows

1
nanoTime()có một vấn đề (ít nhất là trên Windows); dấu thời gian dành riêng cho lõi bộ xử lý. Tôi đã có một chương trình có thời gian thực thi âm vì chương trình có dấu thời gian "bắt đầu" trên một lõi và dấu thời gian "dừng" trên lõi khác.
gustafc

3

Đối với những thứ đơn giản, System.currentTimeMillis () có thể hoạt động.

Nó thực sự phổ biến đến mức IDE của tôi được thiết lập để khi nhập "t0", nó tạo cho tôi dòng sau:

final long t0 = System.currentTimeMillis()

Nhưng đối với những thứ phức tạp hơn, có thể bạn sẽ muốn sử dụng các phép đo thời gian thống kê, như ở đây (cuộn xuống một chút và xem các phép đo thời gian được thể hiện bao gồm độ lệch chuẩn, v.v.):

http://perf4j.codehaus.org/devguide.html


+1 để chỉ ra mã trình tạo tự động. Tôi sử dụng một câu lệnh tương tự mọi lúc và không biết về cách chèn các mẫu mã. Chỉ cần tìm ra cách làm điều đó với nhật thực, và nó chắc chắn sẽ hữu ích!
Jason

Tất cả các dịch vụ của Codehaus đã bị chấm dứt. Liên kết của bạn bây giờ đã bị hỏng.
naXa

2

Sử dụng AOP / AspectJ và @Loggablechú thích từ các khía cạnh jcabi, bạn có thể thực hiện dễ dàng và gọn nhẹ:

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

Mọi cuộc gọi tới phương thức này sẽ được gửi đến cơ sở ghi SLF4J với DEBUGmức ghi. Và mọi thông báo nhật ký sẽ bao gồm thời gian thực hiện.


2

Dưới đây là một số cách để tìm thời gian thực thi trong Java:

1) System.nanoTime ()

long startTime = System.nanoTime();
.....your code....
long endTime   = System.nanoTime();
long totalTime = endTime - startTime;
System.out.println("Execution time in nanoseconds  : " + totalTime);
System.out.println("Execution time in milliseconds : " + totalTime / 1000000);

2) System.currentTimeMillis ()

long startTime = System.currentTimeMillis();
.....your code....
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds  : " + totalTime);

3) Instant.now ()

long startTime = Instant.now().toEpochMilli();
.....your code....
long endTime = Instant.now().toEpochMilli();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds: " + totalTime);

hoặc là

Instant start = Instant.now();
.....your code....
Instant end = Instant.now();
Duration interval = Duration.between(start, end);
System.out.println("Execution time in seconds: " +interval.getSeconds());

4) Date.getTime ()

long startTime = new Date().getTime();
.....your code....
long endTime = new Date().getTime();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds: " + totalTime);

1

sử dụng lâu startTime=System.currentTimeMillis()trong thời gian bắt đầu, ở đầu vòng lặp

đặt long endTime= System.currentTimeMillis();bên ngoài cuối vòng lặp. Bạn sẽ phải trừ các giá trị để có thời gian chạy tính bằng mili giây.

Nếu bạn muốn thời gian tính bằng nano giây, hãy xem System.nanoTime()


1

Tôi đã tạo một hàm thứ tự cao hơn lấy mã bạn muốn đo lường trong / dưới dạng lambda:

class Utils {

    public static <T> T timeIt(String msg, Supplier<T> s) {
        long startTime = System.nanoTime();
        T t = s.get();
        long endTime = System.nanoTime();
        System.out.println(msg + ": " + (endTime - startTime) + " ns");
        return t;
    }

    public static void timeIt(String msg, Runnable r) {
       timeIt(msg, () -> {r.run(); return null; });
    }
}

Gọi nó như thế:

Utils.timeIt("code 0", () ->
        System.out.println("Hallo")
);

// in case you need the result of the lambda
int i = Utils.timeIt("code 1", () ->
        5 * 5
);

Đầu ra:

mã 0: 180528 ns
mã 1: 12003 ns

Đặc biệt cảm ơn Andy Turner , người đã giúp tôi cắt giảm phần dư thừa. Xem tại đây .



0

Bạn cũng có thể thử Perf4J. Đó là một cách gọn gàng để thực hiện những gì bạn đang tìm kiếm và giúp thống kê hiệu suất tổng hợp như trung bình, tối thiểu, tối đa, độ lệch chuẩn và giao dịch mỗi giây trong một khoảng thời gian nhất định. Trích dẫn từ http://perf4j.codehaus.org/devguide.html :

StopWatch stopWatch = new LoggingStopWatch();

try {
    // the code block being timed - this is just a dummy example
    long sleepTime = (long)(Math.random() * 1000L);
    Thread.sleep(sleepTime);
    if (sleepTime > 500L) {
        throw new Exception("Throwing exception");
    }

    stopWatch.stop("codeBlock2.success", "Sleep time was < 500 ms");
} catch (Exception e) {
    stopWatch.stop("codeBlock2.failure", "Exception was: " + e);
}

Đầu ra:

INFO: start[1230493236109] time[447] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493236719] time[567] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493237286] time[986] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493238273] time[194] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493238467] time[463] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493238930] time[310] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239241] time[610] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493239852] time[84] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239937] time[30] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239968] time[852] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]

0
public class someClass
{
   public static void main(String[] args) // your app start point
   {
       long start = java.util.Calendar.getInstance().getTimeInMillis();

       ... your stuff ...

       long end = java.util.Calendar.getInstance().getTimeInMillis();
       System.out.println("it took this long to complete this stuff: " + (end - start) + "ms");
   }
}

0

Sử dụng System.currentTimeMillis () là cách thích hợp để thực hiện việc này. Tuy nhiên, nếu bạn sử dụng dòng lệnh và bạn muốn thời gian cho toàn bộ chương trình gần như nhanh chóng, hãy nghĩ đến:

time java App

cho phép bạn không sửa đổi mã và thời gian cho Ứng dụng của mình.


Điều này phụ thuộc vào cách bạn chạy mã. Nếu đó là một đoạn mã chạy máy chủ, thì bạn sẽ bao gồm thời gian khởi động không chính xác.
Arun Ramakrishnan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.