2010-01-20 72 views
21

Trình duyệt nào nhanh hơn trong Java và tại sao?Là Math.max (a, b) hoặc (a> b)? A: b nhanh hơn trong Java?

  1. Math.max(a,b)
  2. (a>b)?a:b

(Điều này đã được hỏi trong một cuộc phỏng vấn.)

+18

Tôi tự hỏi người phỏng vấn đang hy vọng đạt được điều gì bằng cách đặt ra một câu hỏi như vậy. – Seth

+0

bạn nên hỏi lại cái nào dễ đọc hơn, đó là cách quan trọng hơn. Math.max (a, b) KHUYẾN CÁO cho thấy ý định của nó tốt hơn vì vậy đó là câu trả lời đúng –

+13

Tôi thực sự ghét khi mọi người hỏi câu hỏi luật sư ngôn ngữ tại một cuộc phỏng vấn. Có ai thực sự nghĩ rằng khả năng của bạn là một lập trình viên năng suất có tương quan chặt chẽ với khả năng của bạn để ghi nhớ các minutiae của một spec ngôn ngữ? – dsimcha

Trả lời

20

Math.max(a, b) là một hàm tĩnh (có nghĩa là không có chi phí cuộc gọi ảo) và có khả năng sẽ được inlined bởi JVM với các hướng dẫn tương tự như (a > b) ? a : b.

+3

trình biên dịch không trực tiếp các lệnh JVM, trình biên dịch JIT inline mã máy :) –

+0

@BlueRaja: Tôi đã chỉnh sửa câu trả lời của tôi, vì về mặt kỹ thuật bạn đúng (tôi nghĩ), nhưng nó thực sự là một chi tiết nhỏ trong bối cảnh của câu hỏi . – dsimcha

+1

IIRC, JIT sẽ không thực sự thực hiện bất kỳ tối ưu hóa nào cho đến khi khối được đề cập đã được thực thi nhiều (hàng nghìn lần). Câu trả lời an toàn duy nhất cho câu hỏi hiệu suất (đặc biệt là trong Java) là: "Nó phụ thuộc ..." – TMN

20

Here là mã cho Math.max() trong Java:

public static int max(int a, int b) { 
    return (a >= b) ? a : b; 
} 

Vì vậy, các mã có lẽ sẽ là (gần như) chính xác cùng tốc độ.

(Cho phép Thành thật mà nói, nếu bạn đang lo lắng về việc cải tiến tốc độ ở mức thấp như vậy, bạn có thể có vấn đề lớn hơn nhiều trong mã của bạn.)

+1

Trên thực tế, mã cho câu hỏi vẫn còn chi nhánh khi 'a' và' b' là bằng nhau mà sẽ làm cho nó tồi tệ hơn. Tôi biết ai đó sẽ nói gì đó về tra cứu phương pháp nhưng, thành thật mà nói, không sử dụng Java nếu bạn quan tâm đến điều đó. Khi ai đó nhìn thấy 'Math.max' họ biết bạn đang làm gì và đó là điều quan trọng. –

+1

Tại sao phân nhánh trên 'a == b' lại tệ hơn? Giả sử rằng 'a' và' b' là ngẫu nhiên ngẫu nhiên 'int' s. Sau đó, sẽ không 'a> b' chi nhánh bằng nhau thường xuyên như' a> = b'? –

+4

@ Sinan: Khi bạn nhìn vào bytecode, bạn có thể thấy toán tử có điều kiện luôn luôn là nhánh, do đó, sử dụng '> =' thay vì '=' sẽ chỉ làm cho nó sử dụng tuyến khác khi các giá trị bằng nhau. Và các máy ảo Java hiện tại có thể đạt được hiệu năng đáng kinh ngạc cũng cho các hoạt động ở mức độ thấp đôi khi khó đánh bại ngay cả khi C hoặc ASM. Hiệu suất cao và Java không nhất thiết phải là mâu thuẫn nữa nếu bạn biết phải tránh những gì. – x4u

-1

Không giống nhau. Khi bạn đang viết (a > b) ? a : b bạn không có cuộc gọi chức năng bổ sung, vì vậy nó sẽ nhanh hơn. Nó tương đương với nội tuyến trong C++. Nhưng điều này sẽ không tạo ra bất kỳ sự khác biệt nào trong cuộc sống thực. Math.max(a,b) dễ đọc hơn vì vậy tôi sẽ sử dụng nó.

+0

không, hãy xem câu trả lời của dsimcha –

+0

Bất kỳ cuộc gọi chức năng nào đều sẽ thêm phí, ngay cả khi không phải là ảo. Nếu bạn kiểm tra mã máy, bạn sẽ thấy rằng khi hàm được gọi, các tham số được đóng gói trên ngăn xếp; khi hàm sẽ trả về, giá trị kết quả được trích xuất từ ​​ngăn xếp. Tất cả điều này sẽ tiêu thụ chu kỳ CPU. – XMLDUDE

+2

Những gì bạn mô tả chính xác là những gì tối ưu hóa nội tuyến được thiết kế để có được xung quanh. Các chức năng nhỏ như max hầu như luôn được trình bày bởi bất kỳ trình biên dịch hay JIT nào. – dsimcha

9

câu hỏi Performance luôn gọi cho một thử nghiệm trước khi bạn có thể bắt đầu suy đoán:

public static void maxtest() 
{ 
    int res = 0; 
    for(int idx = 0; --idx != 0;) 
     // res = (res > idx) ? res : idx; 
     res = Math.max(res, idx); 
    System.out.println("res: " + res); 
} 

này chạy trên máy tính của tôi trong 6 giây với Math.max() và 3,2 giây với ?: trên máy chủ 1.6.1 x64 mới nhất Sun JVM. Vì vậy, ?: thực sự nhanh hơn. Trái với tất cả những hy vọng chúng tôi muốn đưa vào các JIT đã thực sự trở nên tuyệt vời bởi thời gian họ vẫn không nắm bắt được mọi thứ.

EDIT: Ngoài sự tò mò, tôi cũng đã thử mã này với máy khách 32 bit JVM 1.6.1 trên cùng một máy và với cả hai phiên bản này chạy trong 7 giây! Vì vậy, nó có lẽ không phải là lời gọi phương thức mà không nhận được nội tuyến nhưng máy chủ JIT dường như có thể làm một số tối ưu hóa bổ sung cho trường hợp thử nghiệm cụ thể này mà nó không thể phát hiện khi có một cuộc gọi phương thức có liên quan.

+1

Đó là sự khác biệt ít hơn một vòng lặp trên mỗi vòng lặp. Có lẽ không đáng kể. –

+0

Ồ, và dĩ nhiên 'Math.max' được định nghĩa hơi khác với cách thay thế của bạn, và bạn hầu như luôn luôn theo cùng một con đường (có thể gây ra hiện tượng hiếm khi xảy ra) –

+0

Tôi chạy nó bằng'> = 'và'> 'trong điều kiện và thời gian thực hiện vẫn như cũ. – x4u

3

Tôi đã ở đầu tiếp nhận loại câu hỏi này và chúng thường là nhiều hơn về cách bạn trả lời câu hỏi hơn câu trả lời 'chính xác'.

1

Nếu tôi đã hỏi câu hỏi như vậy trong một cuộc phỏng vấn, tôi đã mong đợi ứng cử viên cho tôi biết rằng hai biểu thức có thể không cho kết quả tương tự cho tất cả các loại a và b.

+0

Cái gì? Tôi không thấy nó như thế nào. Các toán tử so sánh chỉ hoạt động trên các nguyên thủy, do đó hành vi được xác định rõ ràng (trừ khi tôi thiếu một số thứ). Vui lòng giải thích. –

+1

Bạn đang thiếu gấp đôi, float, Double.NaN và Float.NaN. –

+0

Và sự khác biệt giữa số không dương và âm. – jarnbjo

1

Câu hỏi ban đầu không chỉ định loại đối số. Điều này quan trọng bởi vì định nghĩa của max (và min) đối với các đối số dấu chấm động phức tạp hơn. Đối với điểm nổi (double hoặc float), phương thức Math.max có thể chậm hơn, nhưng nó cũng có thể trả về một kết quả khác nếu một trong các đối số là NaN.

0

Không dựa vào suy đoán. Thay vào đó, điểm chuẩn trường hợp sử dụng cụ thể của bạn.

Một số dễ dàng bỏ qua các chi tiết trong rất nhiều các câu trả lời khác:

Trong khi bạn có thể thấy một nguồn Java của Math.max, đây thực sự là không phải lúc nào những gì sẽ được sử dụng. Phương pháp này có phiên bản nội tại trong hầu hết mọi JRE. Xem source code of Hotspot in JDK7, vmSymbols.hpp để biết danh sách nội tại như vậy.

Theo như tôi có thể biết, Hotspot sẽ thử một số tối ưu hóa khi thấy câu hỏi max hoặc min; đặc biệt để tối ưu hóa ví dụ: arraycopy. Trong số những người khác, nó sẽ thực sự tối ưu hóa Math.max(same, same).

Trong các trường hợp khác, tuy nhiên, nó không thể tối ưu hóa nhiều; (a<=b)?a:b có thể thực sự nhanh hơn. Tôi đã chuẩn bị một chút, và thực sự tôi thường thấy điều này nhanh hơn. Nhưng YMMV, và nó chắc chắn phụ thuộc vào bối cảnh nếu Hotspot có thể tối ưu hóa một cái tốt hơn hay cái kia. Nó cũng sẽ thay đổi từ phiên bản điểm phát sóng sang phiên bản hotspot ...

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