So Sánh Giữa Các Máy Ảo, Triển Khai Của Lua 5 - nói dối e blog

So Sánh Giữa Các Máy Ảo, Triển Khai Của Lua 5

Sau khi hoàn thành máy ảo và trình biên dịch cá nhân, tôi từng tiến hành so sánh hiệu năng với Lua 5. Kết quả thu được khá thất vọng - máy ảo của tôi chỉ đạt khoảng 50-60% tốc độ của Lua 5. Điều này khiến tôi không phục, nên đã dành thời gian nghiên cứu mã nguồn Lua 5 kỹ hơn. Thực tế trước đó tôi đã từng đọc qua mã nguồn Lua từng phần, thậm chí nghiên cứu cả Lua 4 và Lua 5 vào những giai đoạn khác nhau, dĩ nhiên tôi hiểu rõ sự khác biệt mang tính cách mạng giữa hai phiên bản này.

Với các chương trình đơn giản, máy ảo của tôi lại có ưu thế tốc độ rõ rệt, nhanh hơn Lua rất nhiều. Tôi cho rằng điều này xuất phát từ kỹ thuật lập trình tinh tế. Tuy nhiên về mặt thiết kế kiến trúc, tôi đã bị thua kém. Lua 5 từ lâu đã áp dụng kiến trúc máy ảo dựa trên thanh ghi (register-based), trong khi tôi vẫn còn sử dụng kiến trúc dựa trên ngăn xếp (stack-based). Dù đã cải tiến thiết kế theo hướng kết hợp giữa hai mô hình, nhưng hiệu năng vẫn không thể sánh được với kiến trúc thuần thanh ghi.

Gần đây tôi dành thời gian phân tích kỹ độ phức tạp trong việc triển khai máy ảo dựa trên thanh ghi. Mặc dù hoàn toàn có khả năng phát triển tiếp, nhưng do dự án hiện tại đang gặp áp lực tiến độ, tôi quyết định tạm gác lại để dành thời gian suy ngẫm và tích lũy thêm kinh nghiệm.

Hôm nay là ngày nghỉ, tôi đọc qua các email trong danh sách đăng ký Lua, đặc biệt quan tâm đến những thay đổi trong Lua 5.1. Vì gần đây tôi đã thực hiện nhiều công việc tương tự, nên dễ dàng hiểu được những tiến bộ của Lua. Điều thú vị là các cải tiến chính của Lua tập trung vào hệ thống thu gom rác (GC). Điều này trùng hợp với điểm mạnh của tôi - hệ thống GC do tôi thiết kế là thứ khiến tôi tự hào nhất, thậm chí còn vượt trội hơn Lua. Trong khi Lua đang phát triển GC thế hệ (generational GC), tôi lại đang nghiên cứu phương án song song (parallel GC) để giải quyết các vấn đề nan giải liên quan đến thu gom bộ nhớ. Tuy nhiên cần lưu ý rằng GC của Lua không hỗ trợ dồn nén bộ nhớ, nên hiệu suất sẽ bị ảnh hưởng trong môi trường có giới hạn bộ nhớ nghiêm ngặt. Ngoài ra, để tối ưu tốc độ, Lua gặp khó khăn với đệ quy sâu - tôi đã từng viết chương trình tính tổng dãy số bằng đệ quy với độ sâu lớn, Lua không thể xử lý được trong khi máy ảo của tôi vẫn vận hành trơn tru. Dù vậy, đây không phải vấn đề đáng lo ngại trong các ứng dụng thông thường.

Với hơn 10 năm phát triển, Lua có rất nhiều điểm đáng để học hỏi. Dự án của tôi chỉ là một sản phẩm thử nghiệm trong 3 tuần ngắn ngủi, coi như bước khởi đầu cho việc rèn luyện kỹ năng. Hôm nay tôi đọc kỹ bài viết “The Implementation of Lua 5.0”, nếu bạn quan tâm đến việc xây dựng ngôn ngữ kịch bản thì nên tham khảo tài liệu này. Qua bài viết, chúng ta hiểu rõ hơn về nhiều khía cạnh (mặc dù có thể tự tìm hiểu qua mã nguồn, nhưng đọc bài viết sẽ thoải mái hơn nhiều).

Lua 5 là máy ảo dựa trên thanh ghi hoàn chỉnh, có thể nói là máy ảo kịch bản đầu tiên áp dụng kiến trúc này một cách rộng rãi. Điều này thật ấn tượng khi so sánh với các nền tảng lớn như Java JVM hay .NET vẫn đang sử dụng kiến trúc dựa trên ngăn xếp. Nghe nói Perl 6 cũng đang chuyển sang mô hình dựa trên thanh ghi :) và ngôn ngữ của tôi cũng có kế hoạch tương tự, haha. Rõ ràng việc phát triển máy ảo dựa trên thanh ghi là một thách thức không nhỏ.

Lua 5 đã tối ưu hóa việc triển khai bảng (table) - điều tôi từng đề cập trong blog trước đây, và tài liệu này cũng phân tích chi tiết vấn đề này. Ngoài ra, Lua 5 bổ sung hỗ trợ coroutine. Tôi đã từng nghiên cứu vấn đề này, đặc biệt sau khi cải tiến máy ảo của mình để không phụ thuộc vào ngăn xếp hệ thống, việc tạo nhiều thread chỉ đơn giản là tạo thêm các ngăn xếp độc lập. Lua 5 cũng áp dụng cơ chế tương tự với mỗi coroutine có ngăn xếp riêng (thực tế sử dụng hai ngăn xếp).

Lua sử dụng trình biên dịch một lượt (one-pass) dựa trên thuật toán đệ quy xuống (recursive descent). Bài viết đề cập rằng việc xây dựng trình biên dịch một lượt đòi hỏi kỹ thuật phức tạp, điều mà tôi đã trải nghiệm thực tế. Những ngày viết trình biên dịch, tôi phải vật lộn với hàng tá vấn đề, suốt hai ngày trời không dám commit bất kỳ dòng code nào. Tuy nhiên lợi ích mang lại rất rõ rệt như tài liệu mô tả: gọn nhẹ, hiệu quả, dễ di chuyển (portable) và hoàn toàn có thể gọi lại (reentrant).

Gần đây tôi từng suy nghĩ về việc giảm kích thước thông tin mô tả kiểu dữ liệu trong ngôn ngữ yếu kiểu. Lua sử dụng một từ độc lập để mô tả kiểu, sau đó dùng union để lưu trữ các kiểu dữ liệu khác nhau - đây cũng là phương pháp tôi đang áp dụng. Tôi từng nghĩ đến việc tận dụng các bit dư thừa trong con trỏ do hiện tượng căn chỉnh (alignment) - ví dụ với căn chỉnh 8 byte, hai bit cuối cùng luôn bằng 0 (ba bit với căn chỉnh 8 byte). Những bit này có thể dùng để lưu trữ thông tin kiểu dữ liệu. Với số nguyên, việc sử dụng 30-31 bit là hoàn toàn khả thi.

Khi đọc tài liệu này, tôi phát hiện ra ý tưởng của mình đã được áp dụng trước đây trong Smalltalk80. Tuy nhiên tài liệu cũng giải thích lý do Lua không sử dụng phương pháp này. Dù vậy, tôi vẫn dự định thử nghiệm phương pháp này trong ngôn ngữ của mình.

Về tập lệnh (instruction set), Lua 5 sử dụng cấu trúc 4 byte mỗi lệnh, cách triển khai rất tinh tế. Tôi đã từng nghiên cứu kỹ phần này khi tìm hiểu tại sao ngôn ngữ của mình chạy chậm hơn. Hóa ra các thao tác đơn giản như i=i+1 trong vòng lặp lại là điểm yếu của máy ảo dựa trên ngăn xếp. Trong khi đó, máy ảo dựa trên thanh ghi như Lua xử lý hiệu quả hơn nhiều. Ngoài ra, mỗi lệnh của tôi sử dụng 8 byte trong khi Lua chỉ cần 4 byte - kích thước dữ liệu ngắn hơn rõ ràng mang lại hiệu suất cao hơn.

Đọc xong tài liệu này, tôi nhận ra Lua có nhiều điểm vượt trội so với Python về hiệu năng. Điều này trùng khớp với trải nghiệm của tôi tại phiên thảo luận Lua tại GDC2004, nơi có thể dễ dàng nhận thấy sự cạnh tranh giữa hai cộng đồng Lua và Python. Tôi tin rằng tại GDC2006, cộng đồng Lua sẽ tự tin hơn bao giờ hết. Hai năm trước, số người dùng Lua 4 còn nhiều hơn Lua 5 (tôi đã từng yêu cầu khán giả giơ tay biểu quyết khi trình bày), nhưng với sự ra mắt của Lua 5.1, vị thế của Lua trong ngành công nghiệp game đã trở nên vững chắc

0%