Tôi không thực sự biết nhiều về nội bộ của trình biên dịch và tối ưu hóa JIT, nhưng tôi thường cố gắng sử dụng "ý thức chung" để đoán những gì có thể được tối ưu hóa và những gì không thể. Vì vậy, hôm nay tôi đã viết một phương pháp thử đơn vị đơn giản:Làm cách nào để viết mã (kiểm tra) sẽ không được tối ưu hóa bởi trình biên dịch/JIT?
@Test // [Test] in C#
public void testDefaultConstructor() {
new MyObject();
}
Phương pháp này thực sự là tất cả những gì tôi cần. Nó kiểm tra rằng constructor mặc định tồn tại và chạy mà không có ngoại lệ.
Nhưng sau đó tôi bắt đầu nghĩ về hiệu ứng của tối ưu hóa trình biên dịch/JIT. Trình biên dịch/JIT có thể tối ưu hóa phương pháp này bằng cách loại bỏ hoàn toàn câu lệnh new MyObject();
không? Tất nhiên, nó sẽ cần phải xác định rằng đồ thị cuộc gọi không có tác dụng phụ cho các đối tượng khác, đó là trường hợp điển hình cho một nhà xây dựng bình thường mà chỉ đơn giản là khởi tạo trạng thái nội bộ của đối tượng.
Tôi cho rằng chỉ JIT mới được phép thực hiện tối ưu hóa như vậy. Điều này có thể có nghĩa rằng nó không phải là một cái gì đó tôi nên lo lắng về, bởi vì phương pháp thử nghiệm đang được thực hiện chỉ một lần. Giả định của tôi có đúng không?
Tuy nhiên, tôi đang cố gắng nghĩ về chủ đề chung. Khi tôi nghĩ về cách ngăn chặn phương pháp này được tối ưu hóa, tôi nghĩ tôi có thể assertTrue(new MyObject().toString() != null)
, nhưng điều này phụ thuộc rất nhiều vào việc thực hiện phương thức toString()
và thậm chí sau đó, JIT có thể xác định phương thức toString()
luôn trả về một giá trị không chuỗi (ví dụ: nếu thực tế là Object.toString()
đang được gọi), và do đó tối ưu hóa toàn bộ nhánh. Vì vậy, cách này sẽ không hoạt động.
Tôi biết rằng trong C# tôi có thể sử dụng [MethodImpl(MethodImplOptions.NoOptimization)]
, nhưng đây không phải là những gì tôi thực sự đang tìm kiếm. Tôi hy vọng sẽ tìm được cách (không độc lập) để đảm bảo rằng một số phần cụ thể của mã của tôi sẽ thực sự chạy như tôi mong đợi, mà không có JIT can thiệp vào quá trình này.
Ngoài ra, có bất kỳ trường hợp tối ưu hóa điển hình nào tôi nên biết khi tạo các bài kiểm tra đơn vị của mình không?
Cảm ơn rất nhiều!
Cảm ơn bạn. Tôi tự hỏi tại sao JIT cư xử theo cách này? Nếu phân bổ đối tượng là vô ích (như thực sự có thể được xác định bằng phân tích tĩnh trong một số trường hợp), tại sao JIT sẽ không tối ưu hóa nó? –
Bây giờ tôi có thể nghĩ về một trường hợp góc, nhưng tôi nghĩ nó đủ hiếm.Nếu phân bổ đối tượng đã được thực hiện ví dụ để đảm bảo rằng đủ bộ nhớ có sẵn cho một số đối tượng khác (và thậm chí đảm bảo không có phân trang sẽ xảy ra), tối ưu hóa sẽ làm mất hiệu lực giả định. –
Cần phải rời khỏi Máy ảo Java (JVM) trong trạng thái phù hợp với việc có mã chương trình thực thi trong JVM theo Mô hình bộ nhớ Java. Không bắt buộc phải thực thi bất kỳ mã cụ thể nào hoặc cấp phát bộ nhớ trong trường hợp JIT có thể chứng minh rằng mã không có hiệu lực trên trạng thái chương trình quan sát được. –