2012-01-23 17 views
6

Ok, tôi đã đọc một số cuộc thảo luận về sự khác biệt giữa JIT và thông dịch viên không hỗ trợ JIT, và tại sao JIT thường tăng hiệu suất.Không thông dịch viên JIT và phi JIT Mã sản phẩm

Tuy nhiên, câu hỏi của tôi là:

Cuối cùng, không một tổ chức phi JIT kích hoạt dịch viên phải bật bytecode (từng dòng) vào máy/mã gốc được thực hiện, giống như một trình biên dịch JIT sẽ làm ? Tôi đã nhìn thấy các bài viết và sách giáo khoa nói điều đó, và các bài viết nói rằng nó không có. Đối số thứ hai là trình thông dịch/JVM thực hiện trực tiếp bytecode này mà không tương tác với máy/mã gốc.

Nếu dịch viên phi JIT làm lần lượt từng dòng vào mã máy, có vẻ như những lợi ích chính của JIT là ...

  1. Các thông tin tình báo của bộ nhớ đệm hoặc tất cả (JIT bình thường) hoặc thường xuyên gặp phải (tối ưu hóa các điểm nóng/thích nghi) các phần của bytecode sao cho mỗi bước biên dịch mã máy không cần thiết.

  2. Bất kỳ trình biên dịch JIT tối ưu nào cũng có thể thực hiện dịch mã bytecode thành mã máy.

Điều đó có chính xác không? Có vẻ như có sự khác biệt nhỏ (không phải là tối ưu hóa có thể, hoặc JITting khối vs dòng theo dòng có thể) giữa việc dịch mã bytecode sang mã máy thông qua các trình thông dịch được kích hoạt không JIT và JIT.

Xin cảm ơn trước.

Trả lời

8

Trình thông dịch không phải JIT không chuyển đổi bytecode thành mã máy. Bạn có thể tưởng tượng được sự vận hành của một cái gì đó không JIT bytecode interpreter như thế này (tôi sẽ sử dụng một giả Java tương tự):

int[] bytecodes = { ... }; 
int ip  = 0; // instruction pointer 
while(true) { 
    int code = bytecodes[ip]; 
    switch(code) { 
    case 0; 
     // do something 
     ip += 1; break; 
    case 1: 
     // do something else 
     ip += 1; break; 
    // and so on... 
    } 
} 

Vì vậy, đối với mỗi bytecode thực hiện, người phiên dịch phải lấy mã, bật giá trị của nó để quyết định phải làm gì và tăng "con trỏ chỉ dẫn" của nó trước khi chuyển sang bước lặp tiếp theo.

Với JIT, tất cả chi phí trên sẽ được giảm xuống thành không có gì. Nó sẽ chỉ lấy nội dung của các nhánh chuyển đổi thích hợp (các phần nói "// làm một cái gì đó"), xâu chuỗi chúng lại với nhau trong bộ nhớ và thực hiện một bước nhảy đến đầu của phần đầu tiên. Không cần "con trỏ chỉ dẫn" phần mềm - chỉ có con trỏ chỉ dẫn phần cứng của CPU. Không truy xuất bytecode từ bộ nhớ và chuyển đổi giá trị của chúng.

Viết một máy ảo không khó (nếu nó không phải là hiệu suất cực cao), và có thể là một bài tập thú vị. Tôi đã làm một lần cho một dự án nhúng, nơi mã chương trình phải rất nhỏ gọn.

+0

Cảm ơn bạn đã phản hồi! Tôi đã đọc qua cuốn sách "Bắt đầu với trò chơi và đồ họa trong C++" và đề cập đến "Người phiên dịch dịch mỗi lệnh cao cấp sang hướng dẫn ngôn ngữ máy tương đương và thực thi ngay lập tức nó." Đó là nơi mà sự nhầm lẫn bắt đầu. Tuy nhiên, nó đã nói về thông dịch viên nói chung. –

+0

Một thông dịch viên "dịch" các lệnh cấp cao sang ngôn ngữ máy bằng cách chuyển/nhảy tới một phần của ngôn ngữ máy thực hiện thao tác được biểu thị bằng lệnh mức cao. –

0

Nhiều thập kỷ trước, dường như có một niềm tin rộng rãi rằng các trình biên dịch sẽ biến toàn bộ chương trình thành mã máy, trong khi phiên dịch sẽ dịch một câu lệnh thành mã máy, thực thi nó, loại bỏ nó, dịch phần tiếp theo. 99% không chính xác, nhưng có hai hạt nhân thật nhỏ bé. Trên một số bộ vi xử lý, một số hướng dẫn yêu cầu sử dụng các địa chỉ được chỉ định trong mã. Ví dụ, trên 8080, có một hướng dẫn để đọc hoặc viết một địa chỉ I/O được chỉ định 0x00-0xFF, nhưng không có hướng dẫn để đọc hoặc viết một địa chỉ I/O được chỉ định trong sổ đăng ký. Nó phổ biến cho các thông dịch viên ngôn ngữ, nếu mã người dùng thực hiện "123,45", để lưu trữ thành 3 byte bộ nhớ, hướng dẫn "out 7Bh/ret", nạp bộ tích lũy với 2Dh và thực hiện cuộc gọi đến đầu tiên những chỉ dẫn đó.Trong tình huống đó, thông dịch viên thực sự sẽ tạo ra một lệnh mã máy để thực hiện lệnh được diễn giải. Tuy nhiên, việc tạo mã như vậy hầu như chỉ giới hạn ở những thứ như lệnh IN và OUT.

Nhiều thông dịch viên Microsoft BASIC phổ biến cho 6502 (và có thể là 8080) đã sử dụng mã mở rộng hơn trong RAM, nhưng mã được lưu trữ trong RAM không phụ thuộc đáng kể vào chương trình đang thực thi; phần lớn các thói quen RAM sẽ không thay đổi trong quá trình thực hiện chương trình, nhưng địa chỉ của lệnh tiếp theo được giữ trong dòng như là một phần của quy trình cho phép sử dụng lệnh "LDA" chế độ tuyệt đối, tiết kiệm ít nhất một chu kỳ mỗi lần tìm nạp byte.