Tại sao các ngôn ngữ VM không được biên dịch chỉ một lần?


8

(Trước hết, tôi nên làm rõ rằng trình biên dịch và máy ảo ( aka ) là một trường hoàn toàn xa lạ với tôi)

Theo tôi hiểu, mỗi khi chạy ứng dụng Java / C # / ..., VM sẽ được gọi và dịch mã trung gian (mã byte, CIL, v.v.) sang hướng dẫn máy.

Nhưng tại sao thao tác này không thể được thực hiện chỉ một lần - tại thời điểm cài đặt?


1
Thời gian cài đặt là gì?
Peter Taylor

3
Không chắc đó có phải là một thuật ngữ chuẩn hay không, nhưng ý tôi là: khi người dùng cài đặt chương trình lần đầu tiên - thay vì biên dịch một chương trình trong máy của nhà phát triển (người không thể biết nền tảng mà người dùng nhất định sẽ sử dụng - và bạn không muốn phân phối một trình cài đặt cho mỗi nền tảng).
vemv

@vemv biên dịch trong thời gian chạy cho phép VM chuyên môn hóa các hướng dẫn máy cho phần cứng cụ thể của bạn
Lucina

Câu trả lời:


8

Trong trường hợp của Java, JVM có thể thực hiện tối ưu hóa vượt qua các ranh giới thư viện. Ví dụ, bạn có thể nội tuyến một phương thức từ thư viện vào mã máy khách của riêng bạn. Loại tối ưu hóa này không thể được thực hiện tại thời điểm biên dịch, bởi vì thư viện có thể thay đổi trước khi thực hiện. Hoàn toàn có thể libfoo-1.0 của bạn được thay thế bằng libfoo-1.1 mà không cần biên dịch lại. Nếu điều đó xảy ra, các dòng trong thư viện chéo được thực hiện tại thời điểm biên dịch sẽ trở nên hoàn toàn không hợp lệ.

Bằng cách thực hiện tối ưu hóa chỉ trong thời gian chạy, không có lo lắng rằng thư viện thay đổi theo bạn sẽ làm mất hiệu lực tối ưu hóa.


1
Một nội tuyến có thể thay vì tạo mã máy để gọi "Y.setX (x)" (trong đó Y là từ thư viện phần thứ ba) sau đó chạy "this.x = x" sau đó chỉ cần tạo mã máy cho "Yx = x ".

Tóm lại, thời gian chạy có thông tin rằng thời gian biên dịch không.
Daniel Gratzer

6

Bởi vì điều này ngăn cản họ sử dụng nhiều tính năng. Ví dụ, làm thế nào JIT có thể tạo ra các cảnh báo chung mới từ các DLL được tải vào thời gian chạy? Những DLL đó không tồn tại tại thời điểm cài đặt.


1
Chúc mừng cho câu trả lời. Tôi nghĩ rằng tôi gặp phải vấn đề tức thời - mặc dù không thể chắc chắn 100% vì câu trả lời của bạn hơi quá. Ngoài ra liệt kê các tính năng không có sẵn khác sẽ làm cho quan điểm của bạn mạnh mẽ hơn.
vemv

3
Hoặc nói chung: một JIT có thể thực hiện tối ưu hóa dựa trên đầu vào; DLL được tải tại thời gian chạy là một loại đầu vào.
amara

1
Rõ ràng, những của DLL được cài đặt là tốt, và mỗi DLL có thể được biên dịch tại của nó thời gian cài đặt. Bạn mất tối ưu hóa mô-đun chéo, nhưng dù sao đó là một chút lý thuyết.
MSalters

@MSalters: Không phải mọi DLL đều có thời gian "cài đặt".
DeadMG

@DeadMG: Dù sao thì chúng tôi cũng đang lo lắng về các hệ thống giả thuyết; một hệ thống như vậy có thể dễ dàng yêu cầu cài đặt. (Nó sẽ là một lợi ích bảo mật, ngoài ra, nếu việc giới thiệu mã thực thi sẽ được quản lý rõ ràng).
MSalters

5

Nó có thể và thường là, ít nhất là với các ứng dụng .NET. Xem Trình tạo hình ảnh gốc

một công cụ cải thiện hiệu suất của các ứng dụng được quản lý. Ngen.exe tạo hình ảnh gốc, là các tệp chứa mã máy cụ thể của bộ xử lý được biên dịch và cài đặt chúng vào bộ đệm hình ảnh gốc trên máy tính cục bộ. Thời gian chạy có thể sử dụng hình ảnh gốc từ bộ đệm thay vì sử dụng trình biên dịch chỉ trong thời gian (JIT) để biên dịch tập hợp gốc ...


Lưu ý rằng điều này cũng tương tự với Thời gian chạy Android (ART) do Google xây dựng để cải thiện hiệu suất của Ứng dụng Android
neelsg

3

Để viết lại câu hỏi theo sự làm rõ:

Tại sao mã byte không thể được biên dịch thành mã gốc trong lần đầu tiên chương trình được chạy?

Tôi thấy các vấn đề sau:

  • Kết quả sẽ được lưu trữ ở đâu? Bạn không thể cho rằng tệp chứa mã byte là có thể ghi được; bạn không muốn làm hỏng máy của nhà phát triển bằng cách bỏ một .exe mới vào bộ nhớ vĩnh viễn mỗi khi anh ta chạy thử nghiệm; và nếu bạn lưu trữ tệp trong bộ lưu trữ tạm thời thì nó sẽ bị mất vào lần tiếp theo bạn khởi động lại, vì vậy bạn đã không thu được nhiều.

  • Lần đầu tiên bạn giao dịch khởi động hơi chậm để khởi động rất chậm. Sẽ không để lại ấn tượng tốt với khách hàng.

  • Bạn sẽ gặp rắc rối đáng kể với việc tải lớp động.


2
Điểm đầu tiên là tầm thường. Bộ nhớ cache được hiểu khá rõ. Khi mã byte thực thi cơ bản bị xóa, bạn có thể xóa mục nhập bộ đệm liên quan và nếu nó không chạy quá lâu. Đối với điểm thứ hai, bạn có thể thực hiện việc biên dịch các phương thức không sử dụng trong một luồng nền. Điều này sẽ không cản trở thời gian khởi động, nơi bạn biên dịch các phương thức được gọi là tiền cảnh.
MSalters

Theo tôi hiểu, câu hỏi không phải là về việc biên dịch ở lần chạy đầu tiên, mà là biên dịch khi cài đặt.
Nemanja Trifunovic

@NemanjaTrifunovic, đọc các bình luận về câu hỏi.
Peter Taylor

1
Tôi sợ tôi đã không giải thích chính mình, xin lỗi. Tôi có nghĩa là lần đầu tiên một ứng dụng được bao giờ chạy, sau đó không có sưu tập hơn nữa sẽ là cần thiết nữa. Giống như khi bạn phải biên dịch chương trình C trước khi sử dụng nó trên Linux.
vemv

1
Tôi nghĩ rằng nó được tính khá nhiều khi cài đặt - các quá trình biên dịch / xây dựng đó đã được viết sẵn cho bạn.
vemv
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.