2015-10-12 16 views
6
public class Test { 

    public static void main(String[] args) { 

     int x = 150_000; 

     long start = System.currentTimeMillis(); 
     for(int i = 0; i < x; i++) {    
      f1(i); 
     } 
     long end = System.currentTimeMillis(); 
     System.out.println((end - start)/1000.0); 
    } 

    private static long f1(int n) { 
     long x = 1; 
     for(int i = 0; i < n; i++) { 
      x = x + x; 
     } 
     return x; 
    } 
} 

Ai đó có thể giải thích lý do tại sao đặt x thành 150_000 hoặc 4_000_000 hoặc thậm chí 2_000_000_000 không thay đổi thời gian thực hiện của vòng lặp này?Tại sao thời gian thực hiện vòng lặp của tôi không thay đổi?

+18

Có lẽ trình biên dịch đủ thông minh để phát hiện rằng không có gì xảy ra trong vòng lặp nên nó tối ưu hóa. – Tunaki

+0

Bạn đã làm thế nào? –

+0

@Tunaki Đó cũng là dự đoán của tôi. 'f1' trả về một số giá trị, nhưng giá trị đó không bao giờ được sử dụng và không có biến nào khác đang được sửa đổi trong phương thức. Nó sẽ có ý nghĩa (với tôi ít nhất) rằng trình biên dịch hoàn toàn bỏ qua cuộc gọi. –

Trả lời

10

Trong khi thực hiện trình biên dịch JIT (JVM) chỉ trong thời gian của JVM biên dịch bytecode java (định dạng lớp) thành bộ chỉ lệnh gốc của máy của bạn. JIT thực hiện một số tối ưu hóa trong quá trình biên dịch. Trong trường hợp này JIT có thể nhận ra các nội dung sau (chỉ đoán):

  • phương pháp f1() không có bất kỳ tác dụng phụ có thể nhìn thấy
  • giá trị trả về của f1() cuộc gọi không được lưu trữ ở bất cứ đâu

do đó JIT chỉ đơn giản là bỏ qua lời gọi f1() từ mã gốc. Có thể sau khi xóa f1() gọi toàn bộ vòng lặp for(int i = 0; i < x; i++) cũng đã bị xóa (vì nó cũng không thay đổi ngữ nghĩa chương trình).

+0

Tôi thích trình biên dịch JIT, mặc dù đôi khi, vào các dịp thực sự hiếm hoi bạn cần phải tính đến nó giúp bạn ra ngoài và tối ưu hóa mã của bạn. Đặc biệt là khi thực hiện kiểm tra hiệu suất. Mô tả hay nhất +1. –

Các vấn đề liên quan