2009-07-21 16 views
34

Trong C + +, tôi có thể khai báo một phương thức "nội tuyến" và trình biên dịch có khả năng nội tuyến nó. Theo tôi hiểu thì không có từ khóa như vậy trong Java.Nội tuyến trong Java

Nội tuyến được thực hiện nếu JVM quyết định làm như vậy? Tôi có thể ảnh hưởng đến quyết định này bằng cách nào đó không?

Trả lời

49

Một vài câu trả lời khác đã gợi ý rằng chỉ có phương pháp cuối cùng có thể được inlined - đây là không đúng sự thật, như HotSpot là đủ thông minh để có thể nội tuyến phi chính thức phương pháp chừng nào họ chưa được ghi đè chưa. Khi một lớp được nạp để ghi đè phương thức, nó có thể hoàn tác tối ưu hóa lớp của nó. Rõ ràng là làm cho phương thức cuối cùng có nghĩa là không bao giờ cần thiết ...

Về cơ bản, hãy để JVM thực hiện công việc của mình - có thể sẽ tốt hơn khi làm việc ở vị trí nội tuyến hơn bạn.

Bạn có gặp phải tình huống mà bạn tin rằng JVM không hoạt động tốt?Giả sử bạn đang sử dụng HotSpot, bạn đã thử sử dụng phiên bản máy chủ thay vì máy khách chưa? Điều đó có thể tạo ra sự khác biệt lớn to.

+28

Trên thực tế HotSpot có thể sử dụng các phương thức nội tuyến (speculatively) ngay cả khi nó bị ghi đè, và gọi phương thức này hầu như đối với các đối tượng không thuộc kiểu mong đợi. Server HotSpot thậm chí sẽ inline hai phiên bản khác nhau của một phương thức (bimorphic inline). –

+2

@Tom: Nếu tôi đưa câu trả lời vào câu trả lời thì sao? –

+3

tốt, tôi chắc chắn đã có trường hợp đã được hotspot không nội tuyến và hướng dẫn sử dụng inline dẫn đến yếu tố 5 cải thiện hiệu suất của một vòng lặp xử lý lõi. –

4

nội tuyến có nhiều khả năng xảy ra nếu các phương pháp trong câu hỏi là:

  • ngắn
  • thức
  • không phụ thuộc vào bất kỳ phương pháp chính thức dài, không

Như đó là những chỉ những trường hợp mà JVM mới có thể chắc chắn về tác động của cuộc gọi.

+1

'final' không tạo ra bất kỳ sự khác biệt nào cho HotSpot. –

+0

@ TomHawtin-tackline Thú vị, bạn có thể xây dựng được không? –

+0

@MCEmperor Có thể thay đổi, nhưng nó chỉ kiểm tra xem có bất kỳ lớp được nạp nào ghi đè phương thức hay không. –

1

Đọc phần này để biết hành vi nội tuyến. http://www.javacoffeebreak.com/articles/thinkinginjava/comparingc++andjava.html

Nó nói rằng phương pháp cuối cùng có thể được Inlined nhưng không phải lúc nào.

+0

Thực tế là bài viết đó ngụ ý việc diễn dịch như là chuẩn mực - "có những trình biên dịch vừa mới xuất hiện trong bài viết này" cho thấy nó hầu như không được cập nhật. VM đã đi một chặng đường dài. –

2
class A { 
    final int foo() { return 3; } 
} 

Cho lớp này, mọi lệnh gọi tới foo() có thể được thay thế bằng hằng số "3". Bất kỳ máy ảo Java1 nào cũng có thể thực hiện điều này, bởi vì từ khóa cuối cùng rõ ràng cho rằng không thể có lớp con ghi đè "int foo()".

nội tuyến phương pháp này cung cấp những lợi ích sau tại trang web cuộc gọi:

  • Không gọi phương thức
  • Không cử động
  • Có thể liên tục lần giá trị, ví dụ. "a.foo() + 2" trở thành 5 không có mã nào được thực thi tại thời gian chạy là
    .

Trong quá khứ, các lập trình viên thường chèn từ khóa thức cho chính xác lý do này. Hoặc để tạo điều kiện thuận lợi hơn cho nội tuyến và tăng tốc độ thực thi, chúng sẽ kết hợp nhiều phương thức nhỏ hơn thành một phương pháp lớn hơn. Nhưng theo nhiều cách, các kỹ thuật như vậy sẽ đánh bại toàn bộ cơ sở của mô đun hóa và khả năng sử dụng lại được xây dựng trong ngôn ngữ lập trình.

JVM hiện đại, như Java HotSpot VM có thể nội tuyến lớp mà không có final. từ khóa **.

(http://java.sun.com/developer/technicalArticles/Networking/HotSpot/inlining.html)

+0

Một từ khóa (để tư vấn cho trình biên dịch) thực hiện một hàm gọi nội tuyến phải có ý nghĩa hơn vì lợi ích của khả năng đọc bạn đôi khi phá vỡ tính toán nhất định trong một số hàm trong khi tại thời điểm bạn muốn các cuộc gọi đó được thực hiện trong thời gian chạy để lưu rất nhiều chức năng gọi điện trên không. – mawia

+0

Trả lời bởi @David Rodriguez dưới đây có ý nghĩa. Nếu từ khóa nội tuyến có nghĩa là CHỈ là một HINT cho trình biên dịch, thì tốt hơn là để trình biên dịch và tin tưởng nó, rằng nó sẽ nội tuyến cuộc gọi bất cứ nơi nào có thể mà không có lời khuyên của chúng tôi. – mawia

+0

Liên kết của bạn dường như bị hỏng, bạn có thể cập nhật liên kết này không? –

1

Có, nếu JVM quyết định thực hiện, có thể. Các cách ảnh hưởng bao gồm thiết lập phương thức tĩnh hoặc cuối cùng.

Tất nhiên, điều quan trọng nhất về nó là cấu trúc của phương thức cần phải thân thiện với nội tuyến. Short giúp, nhưng quan trọng nhất là nó chỉ cần sử dụng các biến cục bộ của nó và các tham số của nó, không có trường nào và các lời gọi phương thức tối thiểu đến các phương thức khác trong cùng một lớp.

Tuy nhiên bạn không nên xem xét tối ưu hóa như vậy sớm, bạn thực sự có thể làm mọi thứ tồi tệ hơn (vì bạn có thể ngắn mạch các tối ưu hóa tiềm năng khác). JVM đôi khi sẽ nhận ra rằng một phương pháp có thể được phác thảo mà không có những gợi ý này.

6

Mặc dù trình biên dịch java có thể thực hiện nội tuyến (đối với các phương thức ngắn hạn ràng buộc) thực nội tuyến nội tuyến sẽ được trình biên dịch JIT thực hiện. Trình biên dịch JIT (HotSpot) sẽ có thể, ngay cả, phương thức nội tuyến ảo. Cách tốt nhất để tương tác với nó là viết một mã đơn giản và súc tích. Rất có thể, mã sử dụng Phản chiếu sẽ không cho phép nội tuyến.

Hy vọng điều đó sẽ hữu ích.

+0

Bạn có thể đưa ra bất kỳ bằng chứng nào cho trình biên dịch Java (trái ngược với trình biên dịch JÍT) các cuộc gọi phương thức nội tuyến không? –

+0

* "Rất có thể, mã sử dụng Phản chiếu sẽ không cho phép nội tuyến" * - [Bài đăng này] (https://stackoverflow.com/questions/14102000/cannot-change-static-final-field-using-java-reflection) dường như có nó theo cách khác, phải không? –

5

'Trong C++ tôi có thể khai báo phương thức "nội tuyến" và trình biên dịch sẽ đặt nội tuyến là' ... hay không. Trình biên dịch là miễn phí để làm cho chức năng nội tuyến hay không và bạn không thể thực sự ảnh hưởng đến kết quả. Nó chỉ là một gợi ý cho trình biên dịch.

Trong Java không có điều đó, trình biên dịch (và sau này là VM trong khi thực hiện tối ưu hóa) có thể quyết định 'nội tuyến' phương thức.

Lưu ý rằng phương thức cuối cùng có nhiều cơ hội được nội tuyến hơn (trình biên dịch không thể nội tuyến phương thức không cuối cùng vì chúng có thể bị ghi đè trong lớp bắt nguồn). Với VM hiện đại, một tối ưu hóa tương tự có thể được thực hiện trong thời gian chạy. VM sẽ gắn cờ kiểu (vì vậy nó có thể thực hiện kiểm tra kiểu) và sẽ nội tuyến mã. Chỉ khi kiểm tra thất bại, nó sẽ rơi trở lại vào cuộc gọi phương thức đa hình chưa được tối ưu hóa ban đầu.

+2

Điểm quan trọng! "inline" không buộc trình biên dịch phải inline phương thức của bạn trong C. –

+0

Thx, bạn nói đúng, tôi quên rằng "inline" là một gợi ý cho trình biên dịch! – CL23

+0

Đôi khi bạn có thể buộc trình biên dịch nội tuyến, nhưng đó là trình duyệt cụ thể hơn: http://stackoverflow.com/questions/934529/c-inline-functions-using-gcc-why-the-call –

1

Khi so sánh hàm bình thường và chức năng cuối cùng (được cho là nội tuyến bởi JVM), tôi đã thấy rằng không có sự cải thiện hiệu suất giữa chúng. Có lẽ trên đầu cuộc gọi hàm đã rất thấp.

Lưu ý: Tôi đã sử dụng thuật toán làm mờ hộp để đánh giá hiệu suất.