Đội ngũ trình giả lập x86 phát hiện đoạn mã quá tệ nên đã sửa luôn trong lúc giả lập
(devblogs.microsoft.com)- Trình giả lập x86-32 đã tạo mã native bằng cách dịch nhị phân để chạy mã x86-32 trên các bộ xử lý khác, mang lại cải thiện hiệu năng lớn so với cách thông dịch
- Có thể hiểu trình giả lập này như việc xem x86-32 là bytecode, còn trình giả lập hoạt động giống một trình biên dịch JIT
- Một chương trình cần cấp phát khoảng 64KB bộ nhớ trên stack và khởi tạo nó; cách thông thường là probe stack, sau đó giảm con trỏ stack rồi khởi tạo bộ nhớ bằng một vòng lặp nhỏ
- Trình biên dịch của đoạn mã đó thay vì tạo vòng lặp đã sinh ra 65.536 lệnh ghi từng byte riêng lẻ; mỗi lệnh dài 4 byte nên để khởi tạo 64KB dữ liệu cần tới 256KB mã
- Đội ngũ trình giả lập đã thêm mã đặc biệt vào bộ dịch để phát hiện hàm này và thay thế nó bằng một vòng lặp ngắn tương đương
Bối cảnh: trình giả lập x86-32 và dịch nhị phân
- Windows từng bao gồm một trình giả lập bộ xử lý x86-32 dành cho các hệ thống chạy trên bộ xử lý không phải x86-32
- Bài gốc không nêu cụ thể trường hợp này áp dụng cho bộ xử lý nào
- Trình giả lập đó dùng dịch nhị phân để tạo ra mã native có hành vi tương đương với mã x86-32 gốc
- Cách này mang lại cải thiện hiệu năng đáng kể so với giả lập dựa trên thông dịch
- Có thể hiểu theo hướng xem x86-32 là bytecode, còn trình giả lập là một trình biên dịch JIT
Đoạn mã gây vấn đề: khởi tạo 64KB bộ nhớ stack
- Một chương trình cần cấp phát khoảng 64KB bộ nhớ trên stack và khởi tạo vùng nhớ này
- Cách tiêu chuẩn là trước tiên thực hiện stack probe để kiểm tra xem có thể sử dụng 64KB bộ nhớ hay không
- Sau đó thường sẽ trừ 65.536 khỏi con trỏ stack, rồi khởi tạo bộ nhớ bằng một vòng lặp nhỏ và chặt chẽ
Trình biên dịch unroll vòng lặp quá mức
- Trình biên dịch dùng cho đoạn mã này đã không tạo ra vòng lặp để khởi tạo từng byte
- Thay vào đó, nó bung vòng lặp thành 65.536 lệnh “ghi byte vào bộ nhớ” riêng lẻ
- Mỗi lệnh có độ dài 4 byte
- Kết quả là để khởi tạo 64KB dữ liệu cần tới 256KB mã
Cách đội ngũ trình giả lập xử lý
- Đội ngũ trình giả lập đã thêm mã đặc biệt vào bộ dịch để phát hiện hàm này
- Khi phát hiện, hàm đó được thay bằng một vòng lặp ngắn thực hiện hành vi tương đương
- Cách xử lý này không đơn thuần dịch nguyên trạng mã gốc của chương trình, mà là trong lúc giả lập sẽ biến mẫu mã kém hiệu quả thành một dạng ngắn gọn hơn
1 bình luận
Ý kiến trên Lobste.rs
Khá thích bình luận giải thích loop unrolling cho Raymond Chen
Không phải ai đọc những bài như thế này cũng biết hết mọi kiến thức nền, nên cũng có nhiều người biết ơn những gợi ý giúp họ học thêm
https://joelonsoftware.com/2004/06/…
Cái này có lẽ là trên Alpha. Vì đã có rất nhiều công sức được bỏ vào trình giả lập x86 cho nền tảng đó