2015-10-05 14 views
5

Tôi hiện đang xem xét một PullRequest chứa này:Tránh gián tiếp và phương pháp dự phòng gọi

-  for (int i = 0; i < outgoingMassages.size(); i++) { 
+  for (int i = 0, size = outgoingMassages.size(); i < size; i++) 

https://github.com/criticalmaps/criticalmaps-android/pull/52

bằng cách nào đó nó cảm thấy không đúng với tôi - sẽ nghĩ rằng vm đang làm những optimisations - nhưng không thể thực sự nói chắc chắn. Rất thích nhận được một số đầu vào nếu thay đổi này có thể có ý nghĩa - hoặc xác nhận rằng điều này được thực hiện trên phía máy ảo.

Trả lời

5

Không, không phải là chắc chắn rằng VM sẽ thay đổi mã của bạn từ

-  for (int i = 0; i < outgoingMassages.size(); i++) { 

để

+  for (int i = 0, size = outgoingMassages.size(); i < size; i++) 

Trong bạn cho vòng lặp có thể là các outgoingMassages sẽ thay đổi kích thước của nó. Vì vậy, JVM không thể áp dụng tối ưu hóa này. Một chuỗi khác có thể thay đổi kích thước outgoingMassages nếu đây là tài nguyên được chia sẻ.

JVM chỉ có thể thay đổi mã nếu hành vi không thay đổi. Ví dụ, nó có thể thay thế một danh sách các chuỗi nối với một chuỗi nối thêm StringBuilder hoặc nó có thể nội tuyến một cuộc gọi phương thức đơn giản hoặc có thể tính giá trị ngoài vòng lặp nếu nó là giá trị không đổi.

+0

Nếu chúng ta biết rằng 'outgoingMassages.size()' sẽ không bị thay đổi? Không phải nó sẽ được tối ưu hóa, bởi vì chúng ta không cần phải gọi đối tượng 'outgoingMassages' và phương thức' size() 'mọi lúc? – HendraWD

+0

@HendraWD nếu bạn biết rằng kích thước của outgoingMessages không thay đổi trong vòng lặp gán kích thước cho biến là một tối ưu hóa có thể được thực hiện. Tuy nhiên, nói chung, tốt hơn là tập trung vào cách giảm thời gian trong mã bên trong vòng lặp. –

+0

ok, cảm ơn bạn đã xác nhận của bạn :) – HendraWD

1

Máy ảo sẽ không thực hiện tối ưu hóa này. Vì có thể kích thước() - Phương thức không trả về cùng một kết quả cho mỗi cuộc gọi. Vì vậy, phương thức phải được gọi là mỗi lần lặp.

Tuy nhiên, nếu kích thước là phương thức getter đơn giản thì tác động hiệu suất rất nhỏ. Có lẽ không thể đo lường được. (Trong một vài trường hợp, nó có thể cho phép Java sử dụng song song mà có thể tạo ra sự khác biệt, nhưng điều này phụ thuộc vào nội dung của vòng lặp).

Sự khác biệt lớn hơn có thể là để đảm bảo rằng vòng lặp có số lần lặp lại được biết trước. Nó không có vẻ hợp lý với tôi trong ví dụ này. Nhưng có lẽ phương pháp được gọi có thể trả lại kết quả thay đổi không mong muốn?

0

Nếu phương pháp size() trên bộ sưu tập của bạn chỉ đưa ra giá trị của một trường riêng, khi đó VM sẽ tối ưu hóa hầu hết điều này (nhưng không hoàn toàn là tất cả). Nó sẽ làm điều đó bằng cách nội tuyến phương thức size() để nó trở thành quyền truy cập vào trường đó.

Các bit còn lại sẽ không được tối ưu hóa là size trong mã mới sẽ được đối xử như final, và do đó liên tục, trong khi lĩnh vực này nhặt từ bộ sưu tập sẽ không được coi là final (có lẽ nó biến đổi từ một chủ đề khác). Vì vậy, trong trường hợp ban đầu, trường sẽ được đọc trong mỗi lần lặp lại, nhưng trong trường hợp mới nó sẽ không.

0

Rất có thể là bất kỳ optimizer phong nha - hoặc tại VM hoặc trong trình biên dịch - sẽ nhận ra:

class Messages { 

    int size; 

    public int size() { 
     return size; 
    } 
} 

public void test() { 
    Messages outgoingMassages = new Messages(); 
    for (int i = 0; i < outgoingMassages.size(); i++) { 

    } 
} 

và tối ưu hóa nó để

for (int i = 0; i < outgoingMassages.size; i++) { 

làm thêm - chưa được kiểm tra - tối ưu hóa nên do đó được coi là evil.

0

Gọi phương thức sẽ xảy ra trên mỗi lần lặp lại vòng lặp và là không miễn phí chi phí. Vì bạn không thể dự đoán tần suất điều này xảy ra, hãy gọi số này sau khi sẽ luôn là ít hơn. Đó là một tối ưu hóa nhỏ nhưng bạn không nên dựa vào trình biên dịch để làm tối ưu hóa cho bạn.

Hơn nữa, các thành viên outgoingMassages ..

private ArrayList<OutgoingChatMessage> outgoingMassages .. 

... nên là một giao diện:

private List<OutgoingChatMessage> outgoingMassages .. 

Sau đó, gọi .size() sẽ trở thành một phương pháp ảo. Để tìm ra lớp đối tượng cụ thể, bảng phương thức sẽ được gọi cho tất cả các lớp của hệ thống phân cấp. Đây không phải là miễn phí một lần nữa.

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