2013-09-06 52 views
5

Java method này được sử dụng trong tiêu chuẩn cho mô phỏng tính toán chậm:Tại sao phương pháp này không được tối ưu hóa?

static int slowItDown() { 
    int result = 0; 
    for (int i = 1; i <= 1000; i++) { 
     result += i; 
    } 
    return result; 
} 

Đây là IMHO một ý tưởng rất xấu, như cơ thể của nó có thể được thay thế bởi return 500500. Điều này dường như không bao giờ xảy ra; có lẽ vì một sự tối ưu hóa như vậy không liên quan đến mã thực như Jon Skeet đã nói.

Thật thú vị, một phương pháp đơn giản hơn một chút với result += 1; được tối ưu hóa hoàn toàn (báo cáo caliper 0.460543 ns).

Nhưng ngay cả khi chúng tôi đồng ý rằng việc tối ưu hóa đi các phương pháp trả về một kết quả không thay đổi là vô ích cho mã thực, vẫn còn là vòng lặp unrolling, mà có thể dẫn đến một cái gì đó giống như

static int slowItDown() { 
    int result = 0; 
    for (int i = 1; i <= 1000; i += 2) { 
     result += 2 * i + 1; 
    } 
    return result; 
} 

Vì vậy, câu hỏi của tôi vẫn là: Tại sao không tối ưu hóa thực hiện ở đây?

Trái với những gì tôi đã viết ban đầu; Tôi chắc đã thấy thứ gì đó không có ở đó.

+1

Làm sao bạn kiểm tra điều này? Nếu sử dụng JIT, bạn có thể sẽ quan sát những thứ tương tự bằng cách thay đổi mã một chút, vì có rất nhiều sự chẩn đoán liên quan. Bạn không có cách nào đảm bảo cho JIT áp dụng ngay cả những tối ưu hóa đơn giản nhất như nội tuyến vì nó chỉ làm như vậy một khi được coi là cần thiết. –

+0

Đây có phải là mã thực sự không? Nếu bạn biết những gì nó có nghĩa là để trở về, tại sao không chỉ viết mã theo cách đó? Tôi là nội dung mà trình biên dịch JIT được điều chỉnh để tối ưu hóa * thực * mã hơn là tối ưu hóa mã đi mà sẽ không xảy ra trong thực tế. (Tối ưu hóa tĩnh có nhiều hơn một chút so với điều này, nhưng hãy nhớ rằng mỗi tối ưu hóa một trình biên dịch JIT cố gắng tìm thấy có một chi phí tại thời gian thực hiện *.) –

+0

@ JonSkeet: Tôi quan sát, lúng túng, liên kết hướng đến mã chuẩn Guava, Tôi thường hy vọng sẽ tin tưởng ... –

Trả lời

3

Vâng, JVM không tối ưu hóa mã như vậy. Câu hỏi đặt ra là bao nhiêu lần nó phải được phát hiện như một điểm phát sóng thực sự (các điểm chuẩn thực hiện nhiều hơn phương pháp đơn này, thường) trước khi nó được phân tích theo cách này. Trong thiết lập của tôi nó yêu cầu 16830 invocations trước khi thời gian thực hiện đã đi đến (gần như) bằng không.

Đúng là mã như vậy không xuất hiện trong mã thực. Tuy nhiên, nó có thể vẫn còn sau khi một số hoạt động nội tuyến của các điểm nóng khác xử lý các giá trị không phải là hằng số biên dịch nhưng hằng số thời gian chạy hoặc hằng số de facto (các giá trị có thể thay đổi theo lý thuyết nhưng không thực tế). Khi một đoạn mã như vậy vẫn là một lợi ích to lớn để tối ưu hóa nó hoàn toàn nhưng điều đó không được dự kiến ​​sẽ xảy ra sớm, tức là khi gọi ngay từ phương pháp chính.

Cập nhật: Tôi đã đơn giản hóa mã và tối ưu hóa thậm chí còn sớm hơn.

public static void main(String[] args) { 
    final int inner=10; 
    final float innerFrac=1f/inner; 
    int count=0; 
    for(int j=0; j<Integer.MAX_VALUE; j++) { 
    long t0=System.nanoTime(); 
    for(int i=0; i<inner; i++) slowItDown(); 
    long t1=System.nanoTime(); 
    count+=inner; 
    final float dt = (t1-t0)*innerFrac; 
    System.out.printf("execution time: %.0f ns%n", dt); 
    if(dt<10) break; 
    } 
    System.out.println("after "+count+" invocations"); 
    System.out.println(System.getProperty("java.version")); 
    System.out.println(System.getProperty("java.vm.version")); 
} 
static int slowItDown() { 
    int result = 0; 
    for (int i = 1; i <= 1000; i++) { 
     result += i; 
    } 
    return result; 
} 

...

execution time: 0 ns 
after 15300 invocations 
1.7.0_13 
23.7-b01 

(64Bit Server VM)

+0

Bạn có thể gửi mã cho bạn không? Tôi tò mò làm thế nào nó xảy ra rằng tất cả đã được tối ưu hóa đi - một tôi đã viết Tôi nghĩ rằng nó đã xảy ra với tôi quá, nhưng bây giờ tôi nghĩ rằng tôi đã nhìn thấy một cái gì đó không có ở đó. – maaartinus

+0

Dường như phương pháp được tối ưu hóa * đi * thay vì được tối ưu hóa (tức là, được gấp thành hằng số). Tôi đã thử một cái gì đó như 'x + = slowItDown()' và in 'x' ở cuối và thời gian không bao giờ dưới 300 ns. Điều này tương ứng với những gì bạn đã viết; nó chỉ là tôi đã tò mò hơn về gấp (vì điều này sẽ phá hủy các điểm chuẩn tôi lấy phương pháp từ). – maaartinus

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