Lưu Ý Khi Nâng Cấp Lên Lua 5.3
Gần đây tôi đang tiến hành nâng cấp một số dự án của công ty từ Lua 5.2 lên Lua 5.3, nhằm chuẩn bị cho việc phát hành phiên bản skynet 1.0 alpha. Trong quá trình cập nhật mã nguồn, tôi đã tổng hợp được một số điểm cần lưu ý như sau:
Lua 5.3 đã loại bỏ các API liên quan đến kiểu dữ liệu “unsigned” và thay thế hoàn toàn bằng kiểu lua_Integer
. Việc chuyển đổi này khá đơn giản, chỉ cần thay đổi API và thêm ép kiểu tương ứng là được. Trong đa số trường hợp, bạn sẽ không gặp vấn đề gì nghiêm trọng với thay đổi này.
Tuy nhiên, phần code cần được kiểm tra kỹ lưỡng nhất chính là các thư viện liên quan đến tuần tự hóa (serialization). Với skynet, cụ thể là các thư viện như sproto, bson và cả protobuffer mà chúng tôi đang sử dụng. Lý do là bởi Lua 5.3 chính thức hỗ trợ kiểu số nguyên (integer), trong khi công việc tuần tự hóa thường yêu cầu phân biệt rõ ràng giữa số thực (float) và số nguyên. Điều này khác với các định dạng dạng văn bản như JSON hay giao thức giao tiếp Redis, vốn không yêu cầu phân biệt này.
Trước đây, để xác định một giá trị number là float hay integer, chúng ta thường phải dùng đồng thời lua_tonumber
và lua_tointeger
rồi so sánh kết quả. Mặc dù mã nguồn cũ này vẫn chạy được trên Lua 5.3, nhưng cách chuẩn bây giờ là sử dụng hàm lua_isinteger
. Ngoài ra, trong một số đoạn code Lua thuần, việc truyền sai kiểu dữ liệu cũng có thể gây lỗi runtime. Ví dụ: khi dùng string.format
với định dạng %d
nhưng lại truyền vào một giá trị float. Lúc này bạn cần thêm math.floor
để xử lý giá trị đầu vào. Đặc biệt lưu ý rằng kết quả của phép chia (dù chia hết hay không) luôn là kiểu float, nên hãy sử dụng toán tử chia nguyên //
mới của Lua 5.3.
Một số thư viện chuẩn cũng có thay đổi đáng kể:
- Thư viện
bit32
đã bị khai tử. Thay vào đó nên sử dụng trực tiếp các toán tử xử lý bit mới được tích hợp sẵn trong Lua 5.3. - Thư viện
utf8
tự viết trước đây nên được thay thế bằng phiên bản chính thức được tích hợp trong Lua 5.3. - Hỗ trợ kiểu
int64
tạm thời trước đây cũng cần được loại bỏ hoàn toàn.
Các cải tiến nổi bật khác:
- Hàm
string.pack
vàstring.unpack
trong Lua 5.3 gần như thay thế hoàn hảo cho thư viện struct thông thường, giúp giảm đáng kể lượng code xử lý luồng nhị phân. - Hàm
unpack
toàn cục đã bị loại bỏ hoàn toàn (từ phiên bản 5.2 đã chuyển sangtable.unpack
), buộc lập trình viên phải cập nhật lại các đoạn code còn sử dụng tên gọi cũ. - Hành vi của
__ipairs
đã thay đổi - giờ đây vòng lặpipairs
sẽ bắt đầu từ chỉ số 1 và dừng lại khi gặp giá trịnil
. Về cơ bản đa số thư viện không cần sửa đổi, nhưng một mô-đun đặc biệt trong hệ thống của chúng tôi đã gặp lỗi loop vô hạn do cách thiết kế “lazy loading” thông qua metamethod__index
.
Một số lưu ý kỹ thuật khác:
- Các thư viện C phân biệt phiên bản Lua bằng macro định nghĩa sẵn (ví dụ: lpeg) cần được cập nhật logic, vì cách cũ có xu hướng gộp chung các phiên bản không phải 5.2 thành 5.1.
- Hàm
lua_gettable
giờ đây trả về trực tiếp kiểu dữ liệu của giá trị lấy được, giúp tối ưu hóa các đoạn code cần kiểm tra giá trị có null hay không.
So với quá trình nâng cấp từ Lua 5.1 lên 5.2, lần này việc chuyển đổi lên Lua 5.3 thuận lợi hơn nhiều nhờ không gặp vấn đề tương thích với JIT. Tôi khuyến khích các dự án đang dùng Lua 5.2 nên dành thời gian nâng cấp lên phiên bản mới để tận dụng các cải tiến mới.
Hiện tại skynet đã có nhánh lua53
chuẩn bị cho phiên bản 1.0 alpha. Các bạn quan tâm tới phát triển skynet nên chuyển sang nhánh này để kiểm tra và đóng góp. Sau khi hoàn tất thử nghiệm trên hệ thống nội bộ, chúng tôi sẽ merge vào master và chính thức phát hành phiên bản 1.0 alpha.