Hãy nhớ rằng những điều sau đây chỉ là so sánh sự khác biệt giữa trình biên dịch gốc và JIT, và không bao gồm các chi tiết cụ thể của bất kỳ ngôn ngữ hoặc khung cụ thể nào. Có thể có những lý do chính đáng để chọn một nền tảng cụ thể ngoài điều này.
Khi chúng tôi tuyên bố rằng mã gốc nhanh hơn, chúng tôi đang nói về trường hợp sử dụng điển hình của mã được biên dịch tự nhiên so với mã được biên dịch JIT, trong đó người dùng sử dụng ứng dụng được biên dịch JIT điển hình, với kết quả ngay lập tức (ví dụ: không chờ trên trình biên dịch trước). Trong trường hợp đó, tôi không nghĩ ai có thể yêu cầu với khuôn mặt thẳng thắn, rằng mã được biên dịch JIT có thể khớp hoặc đánh bại mã gốc.
Giả sử chúng ta có một chương trình được viết bằng một số ngôn ngữ X và chúng ta có thể biên dịch nó với trình biên dịch gốc và một lần nữa với trình biên dịch JIT. Mỗi luồng công việc có cùng các giai đoạn liên quan, có thể được khái quát hóa như (Mã -> Đại diện trung gian -> Mã máy -> Thực thi). Sự khác biệt lớn giữa hai là giai đoạn nào được người dùng nhìn thấy và được lập trình viên nhìn thấy. Với trình biên dịch gốc, lập trình viên nhìn thấy tất cả trừ giai đoạn thực thi, nhưng với giải pháp JIT, người dùng sẽ nhìn thấy việc biên dịch thành mã máy, ngoài việc thực thi.
Khiếu nại rằng A nhanh hơn B đang đề cập đến thời gian để chương trình chạy, như người dùng đã thấy . Nếu chúng ta giả sử rằng cả hai đoạn mã thực hiện giống hệt nhau trong giai đoạn Thực thi, chúng ta phải giả sử rằng luồng công việc JIT chậm hơn đối với người dùng, vì anh ta cũng phải xem thời gian T của quá trình biên dịch thành mã máy, trong đó T> 0. Vì vậy, , đối với bất kỳ khả năng nào của luồng công việc JIT thực hiện giống như luồng công việc gốc, đối với người dùng, chúng ta phải giảm thời gian Thực thi mã, như Thi hành + Biên dịch thành mã máy, thấp hơn chỉ giai đoạn Thực thi của dòng công việc bản địa. Điều này có nghĩa là chúng ta phải tối ưu hóa mã tốt hơn trong quá trình biên dịch JIT so với biên dịch gốc.
Tuy nhiên, điều này là không khả thi, vì để thực hiện các tối ưu hóa cần thiết để tăng tốc Thực thi, chúng ta phải dành nhiều thời gian hơn trong quá trình biên dịch sang giai đoạn mã máy, và do đó, bất cứ khi nào chúng ta lưu lại do mã tối ưu hóa thực sự bị mất, vì chúng tôi thêm nó vào phần tổng hợp. Nói cách khác, "sự chậm chạp" của giải pháp dựa trên JIT không chỉ đơn thuần là do thời gian bổ sung cho quá trình biên dịch JIT, mà mã được tạo bởi quá trình biên dịch đó thực hiện chậm hơn so với giải pháp gốc.
Tôi sẽ sử dụng một ví dụ: Đăng ký phân bổ. Vì truy cập bộ nhớ chậm hơn hàng nghìn lần so với truy cập đăng ký, lý tưởng nhất là chúng tôi muốn sử dụng các thanh ghi bất cứ khi nào có thể và có càng ít truy cập bộ nhớ càng tốt, nhưng chúng tôi có số lượng đăng ký hạn chế và chúng tôi phải tràn vào bộ nhớ khi cần một đăng ký. Nếu chúng tôi sử dụng thuật toán phân bổ đăng ký mất 200ms để tính toán và kết quả là chúng tôi tiết kiệm được 2ms thời gian thực hiện - chúng tôi sẽ không tận dụng thời gian tốt nhất cho trình biên dịch JIT. Các giải pháp như thuật toán của Chaitin, có thể tạo mã được tối ưu hóa cao là không phù hợp.
Vai trò của trình biên dịch JIT là tạo ra sự cân bằng tốt nhất giữa thời gian biên dịch và chất lượng mã được sản xuất, tuy nhiên, với sự thiên vị lớn về thời gian biên dịch nhanh, vì bạn không muốn người dùng chờ đợi. Hiệu suất của mã được thực thi chậm hơn trong trường hợp JIT, vì trình biên dịch gốc không bị ràng buộc (nhiều) theo thời gian trong việc tối ưu hóa mã, do đó, có thể sử dụng các thuật toán tốt nhất. Khả năng biên dịch tổng thể + thực thi cho trình biên dịch JIT chỉ có thể đánh bại thời gian thực hiện đối với mã được biên dịch nguyên gốc là 0.
Nhưng máy ảo của chúng tôi không chỉ giới hạn trong quá trình biên dịch JIT. Họ sử dụng các kỹ thuật biên dịch trước thời gian, bộ nhớ đệm, trao đổi nóng và tối ưu hóa thích ứng. Vì vậy, hãy sửa đổi tuyên bố của chúng tôi rằng hiệu suất là những gì người dùng nhìn thấy và giới hạn thời gian thực hiện chương trình (giả sử chúng tôi đã biên soạn AOT). Chúng ta có thể làm cho mã thực thi tương đương với trình biên dịch gốc (hoặc có lẽ tốt hơn?). Một yêu cầu lớn đối với máy ảo là chúng có thể tạo ra mã chất lượng tốt hơn sau đó là trình biên dịch gốc, bởi vì nó có quyền truy cập vào nhiều thông tin hơn - đó là quá trình đang chạy, như tần suất một hàm nhất định có thể được thực thi. VM sau đó có thể áp dụng tối ưu hóa thích ứng cho mã cần thiết nhất thông qua trao đổi nóng.
Tuy nhiên, có một vấn đề với lập luận này - nó giả định rằng tối ưu hóa theo hướng dẫn hồ sơ và những thứ tương tự là một cái gì đó duy nhất cho VM, điều này không đúng. Chúng ta cũng có thể áp dụng nó cho việc biên dịch riêng - bằng cách biên dịch ứng dụng của chúng ta với cấu hình được kích hoạt, ghi lại thông tin và sau đó biên dịch lại ứng dụng với hồ sơ đó. Có lẽ cũng đáng để chỉ ra rằng trao đổi nóng mã không phải là thứ mà chỉ có trình biên dịch JIT mới có thể làm được, chúng ta có thể làm điều đó cho mã gốc - mặc dù các giải pháp dựa trên JIT để thực hiện điều này dễ dàng hơn và dễ dàng hơn cho nhà phát triển. Vì vậy, câu hỏi lớn là: VM có thể cung cấp cho chúng tôi một số thông tin mà trình biên dịch gốc không thể, điều này có thể tăng hiệu năng của mã của chúng tôi không?
Tôi không thể nhìn thấy nó. Chúng ta cũng có thể áp dụng hầu hết các kỹ thuật của một VM thông thường cho mã gốc - mặc dù quá trình này có liên quan nhiều hơn. Tương tự, chúng ta có thể áp dụng bất kỳ tối ưu hóa nào của trình biên dịch gốc trở lại VM sử dụng trình biên dịch AOT hoặc tối ưu hóa thích ứng. Thực tế là sự khác biệt giữa mã chạy tự nhiên và mã chạy trong VM không lớn như chúng ta đã tin. Cuối cùng họ dẫn đến cùng một kết quả, nhưng họ có một cách tiếp cận khác để đạt được điều đó. VM sử dụng cách tiếp cận lặp để tạo mã được tối ưu hóa, trong đó trình biên dịch gốc mong đợi nó ngay từ đầu (và có thể được cải thiện bằng cách tiếp cận lặp).
Một lập trình viên C ++ có thể lập luận rằng anh ta cần tối ưu hóa từ việc di chuyển và không nên chờ đợi VM tìm ra cách thực hiện chúng, nếu có. Đây có lẽ là một điểm hợp lệ với công nghệ hiện tại của chúng tôi, vì mức độ tối ưu hóa hiện tại trong máy ảo của chúng tôi kém hơn những gì trình biên dịch gốc có thể cung cấp - nhưng điều đó có thể không phải luôn luôn xảy ra nếu các giải pháp AOT trong máy ảo của chúng tôi cải thiện, v.v.