7 điểm bởi GN⁺ 2025-09-23 | 1 bình luận | Chia sẻ qua WhatsApp
  • Luaungôn ngữ scripting nhúng nhanh, an toàn và hỗ trợ kiểu dần dần được phát triển từ Lua 5.1
  • Đã được mở rộng về hiệu năng, công cụ ngôn ngữ và hệ thống kiểu để hỗ trợ các trò chơi phức tạp và codebase quy mô lớn trên nền tảng Roblox
  • Khác với Lua gốc, ngôn ngữ này có tính năng sandboxing và được thiết kế để mã có mức quyền hạn khác nhau có thể chạy song song
  • Cú pháp tương thích với Lua 5.1, đồng thời cung cấp các mở rộng cú pháp bổ sungcông cụ phân tích (linter, type checker) để nâng cao chất lượng mã
  • Với tối ưu hóa hiệu năng, bytecode tùy biến, hỗ trợ JIT..., Luau hướng tới tốc độ thực thi ngang mức LuaJIT và có tiềm năng được dùng trong nhiều môi trường nhúng ngoài Roblox

Motivation (động lực ra đời)

  • Khoảng năm 2006, Roblox đã đưa Lua 5.1 vào làm ngôn ngữ scripting cho game
  • Theo thời gian, khi mức độ phức tạp của game trên nền tảng Roblox tăng lên và quy mô đội ngũ lớn hơn, Roblox đã cải tiến mạnh cả ngôn ngữ lẫn phần triển khai để vượt qua các giới hạn của Lua cũ
  • Cùng với sự phát triển của nền tảng, họ đã đầu tư nhiều vào tối ưu hiệu năng, tính thân thiện với người dùng và phát triển các công cụ liên quan đến ngôn ngữ
  • Đặc biệt, khi quản lý codebase quy mô lớn vượt 1 triệu dòng tính đến năm 2020, Roblox nhận thấy việc đưa vào hệ thống kiểu dần dần là điều thiết yếu
  • Dựa trên những nhu cầu đó, Roblox đã phát triển Luau, một ngôn ngữ dẫn xuất từ Lua, mang lại các đặc tính nhanh, nhỏ gọn, an toàn và có thể áp dụng kiểu một cách dần dần
  • Giải thích chi tiết hơn có trong tài liệu Why Luau

Tổng quan về Luau

  • Luaungôn ngữ scripting nhúng dựa trên Lua 5.1
    • Cung cấp runtime nhanh và nhẹ
    • Hỗ trợ hệ thống kiểu dần dần, cho phép kết hợp phân tích động và tĩnh
  • Được tích hợp trong Roblox Studio, và có thể bật strict mode bằng cờ --!strict
  • Nhà phát triển có thể xem tài liệu liên kết với Roblox tại Luau Creator Docs

Sandboxing (tính năng sandbox)

  • Luau giới hạn thư viện chuẩn được phơi bày ra ngoài và cung cấp các tính năng sandbox bổ sung
  • Nhờ đó, mã không đặc quyền do nhà phát triển thông thường viếtmã đặc quyền nội bộ của nền tảng có thể chạy song song một cách an toàn
  • Vì vậy, môi trường thực thi của Luau khác với Lua gốc
  • Có thể xem chi tiết tại Sandbox mô tả

Compatibility (tương thích)

  • Duy trì khả năng tương thích ngược với Lua 5.1 nhiều nhất có thể, đồng thời tiếp thu một phần tính năng từ các phiên bản mới hơn
  • Tuy nhiên, Luau không chấp nhận mọi quyết định thiết kế của Lua, mà phản ánh các use case và ràng buộc đặc thù của Roblox
  • Tình trạng hỗ trợ các tính năng sau Lua 5.1 được nêu trong Compatibility tài liệu

Syntax (cú pháp)

  • Hoàn toàn tương thích với cú pháp Lua 5.1
  • Đồng thời cung cấp các mở rộng cú pháp hiện đại, quen thuộc để cải thiện trải nghiệm phát triển
  • Có thể xem toàn bộ cú pháp trong Syntax tài liệu

Analysis (công cụ phân tích)

  • Cung cấp công cụ phân tích script để hỗ trợ viết mã đúng hơn

  • Các thành phần gồm:

    • Linter: phát hiện lỗi phổ biến
    • Type Checker: kiểm tra kiểu
  • Có thể chạy bằng công cụ CLI luau-analyze

  • Quy tắc lint xem tại Lint tài liệu, hướng dẫn kiểm tra kiểu xem tại Typecheck tài liệu

Performance (hiệu năng)

  • Cung cấp frontend tùy biến gồm parser, linter, type checker cùng với bytecode, interpreter và compiler được tối ưu hóa
  • Trong một số trường hợp, hiệu năng có thể cạnh tranh với interpreter LuaJIT
  • Hỗ trợ trình biên dịch JIT viết thủ công trên nền tảng x64 và ARM64, có thể cải thiện mạnh hiệu năng của một số chương trình nhất định
  • Runtime vẫn đang tiếp tục được tối ưu và một phần được viết lại để nâng cao hiệu quả
  • Chi tiết đặc tính hiệu năng có trong Performance tài liệu

Libraries (thư viện)

  • Bản thân ngôn ngữ là siêu tập hoàn chỉnh của Lua 5.1
  • Ở thư viện chuẩn, một số hàm đã bị loại bỏ và một số hàm mới được bổ sung
  • Khi được nhúng vào ứng dụng, nó cũng có thể truy cập các thư viện mở rộng riêng theo ứng dụng
  • Có thể xem đầy đủ tài liệu thư viện tại Library tài liệu

1 bình luận

 
GN⁺ 2025-09-23
Ý kiến trên Hacker News
  • Đã từng dùng Lua và LuaJIT trong Lumix Engine rồi chuyển sang Luau vì hệ thống kiểu, nhưng cảm thấy rất khó dùng cho các dự án ngoài Roblox; tài liệu nghèo nàn, cộng đồng gần như không có nên chẳng giúp được gì trong việc giải quyết vấn đề; kích thước lớn hơn Lua hay LuaJIT nên tốc độ biên dịch chậm hơn 7 lần; xử lý bất đồng bộ của API trên thực tế lại bị chặn theo kiểu đồng bộ; còn dùng STL nên có nhiều điểm bất tiện; cũng thường xuyên gặp lỗi liên quan đến phân tích và LSP. Vì vậy đang cân nhắc tìm phương án khác
    • Đội Roblox đang tập trung để sau này có thể dùng Luau ngoài Roblox dễ hơn. Nó đã được dùng tốt ở nhiều nơi như Remedy Entertainment (Alan Wake 2), Digital Extremes (Warframe), GIANTS Software (Farming Simulator 25). Hiện tại đầu tư và hỗ trợ vẫn chủ yếu tập trung trong nội bộ Roblox, nhưng họ đang phát triển Lute, một runtime độc lập cho mục đích tổng quát, và cũng muốn mở rộng hệ sinh thái bằng nhiều công cụ phát triển dựa trên Luau. Vẫn còn ở giai đoạn đầu, nhưng họ đang đầu tư tích cực để hỗ trợ việc dùng bên ngoài và nhiều trường hợp khác nhau. Họ tin rằng để Luau phát triển lành mạnh thì việc thu hút thêm người dùng và các ca sử dụng đa dạng là rất quan trọng
    • Tôi đang dùng Luau cho toàn bộ mã gameplay của một game Unity, hơn 60 nghìn dòng. Tôi muốn tài liệu, đặc biệt là phần tích hợp tùy chỉnh, được cải thiện hơn; hệ thống kiểu mới và LSP cũng vẫn chưa phối hợp thật tốt. Từ sau khi zeux rời nhóm, tôi có hơi lo về định hướng dài hạn. Nhưng bản thân trải nghiệm phát triển thì tôi rất thích: mã Luau có thể hot reload gần như ngay lập tức ngay cả khi game đang chạy, và dự án C++ cũng biên dịch nhanh. Tôi cũng thích việc nó cung cấp môi trường sandbox để hỗ trợ modding. Cộng đồng Discord chính thức cũng khá sôi động
    • Bạn nói biên dịch chậm hơn, nhưng nếu là ngôn ngữ script thì vốn dĩ đâu cần biên dịch mã? Không rõ có phải bạn đang nói đến việc biên dịch chính Luau VM hay không
  • Việc Roblox đang phát triển một runtime Luau cho desktop theo kiểu Node.js thực sự rất thú vị: https://github.com/luau-lang/lute
    • Đã có một runtime Luau hoàn thiện hơn là Lune, tôi đang dùng nó cho script build và tự động hóa file Roblox place, và với mục đích sử dụng của tôi thì nó hoạt động hoàn toàn đủ tốt
    • Cũng có một runtime Luau độc lập khác là Lune
  • Luau có vẻ phức tạp hơn Lua rất nhiều; nhìn theo mã nguồn thì Luau có 120 nghìn dòng C++, còn Lua 5.1 là 14 nghìn dòng C. Tôi nghĩ khi đưa vào một hệ thống kiểu dần dần hoặc tĩnh thì khó tránh khỏi việc trở nên phức tạp. Nếu có một hệ thống kiểu tương đối đầy đủ thì cuối cùng chắc chắn sẽ lớn hơn một ngôn ngữ script động
    • Lua (và ở mức nào đó cả Luau) không phải là ngôn ngữ lớn khi xét ở góc độ học ngôn ngữ, chứ không phải số dòng mã. Runtime cần để chạy không nhất thiết phải phụ thuộc hoàn toàn vào Analysis. Trong Analysis có hai hệ thống kiểu hoàn chỉnh; trong 3 năm gần đây họ đã phát triển một hệ thống kiểu mới để giải quyết các giới hạn căn bản, và giờ hệ thống cũ sắp bị loại bỏ. Khi đó cũng có thể giảm được khoảng 30 nghìn dòng mã
    • Tôi không nghĩ Lua hay Luau là ngôn ngữ nhỏ hoặc đơn giản. Có thể mức độ phức tạp đó không thật sự cần thiết. Tôi đang làm một ngôn ngữ đơn giản hơn mà vẫn biểu đạt tốt tên là Bau, đồng thời cũng phát triển một VM kiểu Lua. Các ngôn ngữ nhỏ như vậy cũng thỉnh thoảng thành chủ đề bàn luận trên Reddit: Bau, Bau VM, r/ProgrammingLanguages
    • Static typing hay gradual typing đúng là làm tăng độ phức tạp, nhưng mức tăng nhỏ hơn nhiều so với tưởng tượng; đôi khi chính ngôn ngữ script động còn phức tạp hơn. Một type checker Hindley–Milner có thể được cài đặt chỉ trong một trang mã, nên mức phức tạp cỡ 2.000 trang ở đây có vẻ hơi quá. H–M dù không xử lý hàm bậc cao, generic (đa hình tham số) hay con trỏ null thì vẫn đã hoàn chỉnh và có thể suy luận toàn phần; cũng có thể mở rộng, và chỉ với phần cơ bản thôi đã mạnh hơn nhiều so với hệ thống kiểu của C hay Java 1.7
    • Tôi đã tự viết type checker cho Lua và cũng đọc rất nhiều mã nguồn của nó; 14 nghìn dòng của Lua là mật độ mã cực cao. Nếu viết theo phong cách bình thường hơn thì sẽ thành khoảng 30–40 nghìn dòng. Nghĩa là Lua không phải nhỏ về bản chất, mà là được viết cực kỳ cô đọng
    • Nếu liệt kê chi tiết hơn số dòng do tokei phân tích, thì thư mục Analysis có 62 nghìn dòng C++, 9.200 dòng header C; Ast có 8.400 dòng C++; CodeGen C++ có 21 nghìn dòng, v.v. Lua 5.1 thì toàn bộ src có 11 nghìn dòng C và 1.900 dòng header
  • Tôi tò mò về khác biệt giữa Teal và Luau; cả hai đều được giới thiệu là "phương ngữ Lua có kiểu tĩnh" nên muốn so sánh https://teal-language.org/
    • Teal biên dịch file Teal sang Lua nên sẽ mang cả ưu và nhược điểm giống mối quan hệ giữa JS và TS. Luau thì có runtime riêng tương thích ngược với Lua, không chỉ là hệ thống kiểu mà còn cải thiện toàn bộ trải nghiệm phát triển, nên hai bên khá khác nhau. Teal có lợi thế là có thể dùng Lua ở bất cứ đâu; ngược lại Luau chỉ chạy trên runtime chuyên dụng của nó, nhưng không có bước biên dịch riêng nên xét từ góc độ nhà phát triển thì khả năng dùng tiện hơn, và cũng không làm mất thông tin kiểu
    • Teal transpile sang Lua, còn Luau là một bản fork của Lua. Nó có thể thay đổi rộng hơn như hiệu năng interpreter riêng, bảo mật, khả năng mở rộng cú pháp, v.v. Roblox lớn tới mức vốn hóa thị trường khoảng 100 tỷ USD và có nhiều lập trình viên chuyên trách làm việc thường trực
    • Luau không phải chỉ là "Lua cộng thêm kiểu", mà là đang đầu tư mạnh vào hệ thống kiểu dần dần và suy luận kiểu, đồng thời cũng cải tiến bản thân ngôn ngữ theo từng bước. Nó được thiết kế xoay quanh trải nghiệm nhà phát triển và hỗ trợ công cụ; vẫn quan tâm đến kích thước nhị phân, nhưng không ưu tiên sự tối giản nghiêm ngặt như Lua. Trọng tâm của nó không hẳn là để nhúng vào các dự án C quy mô lớn như Lua, mà là giúp chính nhà phát triển có trải nghiệm tốt khi dùng ngôn ngữ
  • Thật đáng tiếc khi Lua đã không thể vừa duy trì tương thích quá khứ vừa tiếp tục tiến hóa. Cuối những năm 2000, Roblox và nhiều dự án khác đã chọn Lua 5.1, còn giờ Lua đã lên 5.4 nhưng khả năng tương thích với bản cũ không được giữ tốt. LuaJIT v.v. cũng chỉ hỗ trợ 5.1. Tình hình khá giống Python 2.x/3.x, nhưng cộng đồng Lua phần lớn vẫn có xu hướng tiếp tục dùng 5.1
    • Thực tế còn tệ hơn: luau và luaJIT cũng phát triển theo hướng riêng khác với dự án lua chính thức, nên giờ giữa chúng cũng không còn tương thích hoàn toàn. Tất cả đều tách ra từ Lua 5.1, nhưng giờ cảm giác như không còn một tiêu chuẩn chính thức nào nữa
    • Khác biệt lớn là cộng đồng Lua không công khai chỉ trích chuyện giữ tương thích ngược, nên việc viết mã cho nhiều phiên bản khác nhau khá dễ dàng
    • Khó tìm được thống kê chính thức, nhưng theo cảm nhận thì số người dùng 5.1 và 5.2 còn nhiều hơn 5.4, và có lẽ 5.3 cũng chưa vượt được. LuaJIT thì được quan tâm nhiều nhưng thực tế lại không gặp thường xuyên
    • LuaJIT cũng đã bao gồm một phần tính năng của các bản Lua mới hơn (5.2, 5.3) và còn có thêm nhiều tính năng khác https://luajit.org/extensions.html
  • Điều khiến tôi thấy thú vị nhất là có những trường hợp interpreter của Luau ngang ngửa LuaJIT. Trang hiệu năng giải thích rất hay và cho thấy năng lực kỹ thuật của Roblox https://luau.org/performance
  • Tôi biết đến Luau khi con tôi 13 tuổi bắt đầu quan tâm đến Roblox Studio và tôi cũng vào luau.org xem thử. Kỹ thuật của Roblox thật sự rất ấn tượng
    • Arseny Kapoulkine là một kỹ sư xuất sắc. Nên theo dõi blog hay mạng xã hội của anh ấy. Ngoài luau và engine render của Roblox, anh còn tạo ra meshoptimizer, một thư viện gần như là thứ bắt buộc phải gặp trong ngành đồ họa, và volk thì thậm chí còn được đưa vào cả Vulkan SDK
  • Second Life đang chuyển từ Linden Scripting Language cũ sang Luau. Trước đây họ dùng biên dịch dựa trên Mono, nhưng vì Mono không còn được duy trì nên cần một ngôn ngữ mới. Không chỉ hỗ trợ Luau, mà trình biên dịch LSL cũ cũng đã được đổi để nhắm tới engine thực thi Luau. Hiệu năng cũng được cải thiện đôi chút. Second Life là một môi trường rất đặc thù, nơi có hàng trăm nghìn script hướng sự kiện chạy trên server, nên quản lý tài nguyên không hề dễ; nếu các chương trình không hoạt động vẫn tiêu tốn 1 micro giây mỗi frame thì cộng dồn lại có thể thành vấn đề lớn
    • Khi môi trường beta của Luau mở ra, tôi đã tự dùng thử và cảm nhận hiệu năng tăng lên đáng kể so với hệ thống Mono cũ. Đặc biệt, tốc độ kiểm tra script khi Save đã giảm từ 10 giây xuống gần như tức thì, giúp hiệu quả phát triển tăng mạnh. Tuy vậy, sẽ còn tốt hơn nữa nếu có các hàm helper để xử lý coroutine thuận tiện như CreateThread(fn), Wait(ms) và tính năng Await/Promises như bên FiveM (triển khai Luau Promise). Trong FiveM, những wrapper như vậy giúp tối ưu script và quản lý coroutine dễ hơn. Ví dụ Lua scheduler của FiveM
    • Sau khi đổi VM, điều dễ thấy ngay là overhead trước đây tập trung nhiều ở scheduling, chuyển ngữ cảnh và cách cài đặt các hàm thư viện. Luau về mặt thiết kế hỗ trợ preemptive scheduling rất tự nhiên, nên việc điều phối phần glue code đơn giản trở nên dễ hơn nhiều. Xử lý việc đó ở cấp VM rẻ hơn và cũng dễ cài đặt hơn nhiều so với biến đổi thành state machine ở tầng AST hay bytecode. Overhead cỡ micro giây của các chương trình idle cuối cùng cũng là đối tượng mà scheduler phải tối ưu
  • Sức hấp dẫn tối giản vốn có của Lua phần nào bị tổn hại vì type inference, nhưng đó là đánh đổi để lấy an toàn kiểu nên cũng có mặt được mặt mất. Dù vậy, tôi đã khá bất ngờ khi sau khi khai báo --!strict, mã vẫn chạy mà không có bất kỳ lỗi hay cảnh báo nào ngay cả khi có vi phạm kiểu rõ ràng. Nó không giống như hành vi tôi kỳ vọng
    • Hiện tại hệ thống kiểu của Luau không phải là "bắt buộc (strict)". Bạn vẫn có thể chạy mã mà không cần kiểm tra kiểu, và nếu chạy trực tiếp bằng demo hay file thực thi luau thì việc kiểm tra kiểu sẽ không được áp dụng. Nếu trong môi trường nhúng bạn buộc toàn bộ mã phải được type check trước khi biên dịch, thì sẽ có trải nghiệm đúng như kỳ vọng là lỗi kiểu bị bắt ra. Đây là hệ quả tất yếu của thiết kế, vì họ đã chuyển hàng triệu dòng mã Lua 5.1 sang Luau cùng một lúc
  • Tôi luôn muốn có Typed Lua, nhưng việc triển khai hoàn chỉnh type checker và LSP cho ngôn ngữ động thật sự khá khó. Ngôn ngữ động nào cũng có những vấn đề tương tự về structural typing, giống như những gì TypeScript gặp phải. Tôi tự hỏi liệu có thể tái sử dụng engine của TypeScript, chuyển một phần mã Luau sang TypeScript để kiểm tra bằng tsc rồi ánh xạ lỗi/kết quả trở lại Luau hay không; như vậy có thể tạo type checker nhanh cho nhiều ngôn ngữ động khác nhau chăng
    • Giống như LLVM là IR chung cho compiler, có lẽ cũng có thể dùng TypeScript type system như một backend chung, một "ngôn ngữ trung gian" cho hệ thống kiểu. Tôi không đặc biệt thích ngôn ngữ động, nhưng nếu có được mức kiểm tra kiểu và hỗ trợ công cụ như TypeScript thì sẽ hứng thú hơn nhiều. Những phần không làm được thì chấp nhận bỏ qua, vì đó cũng là bản chất của gradual typing. Nếu TypeScript type system xuất hiện trong runtime của Lua thì tôi chắc chắn muốn thử; tôi cũng rất quan tâm đến hướng đi của Luau
    • Luau đã có một Luau Language Server rất tốt, nên trong vscode, nvim, zed, v.v. có chẩn đoán, tự động hoàn thành và kiểm tra kiểu nghiêm ngặt rất xuất sắc. Trải nghiệm phát triển của tôi với nó tốt hơn nhiều so với Ruby hay Python. Tôi đang dùng Luau cho shell scripting lẫn lập trình tổng quát, và cũng đã tự làm một runtime kiểu node tên là seal. Còn các nhà phát triển Roblox thì nghe nói chuộng Lune hơn cho CI/CD, testing, v.v.
    • Để dùng TypeScript mà bao phủ mọi ngóc ngách của ngôn ngữ động thì hệ thống sẽ trở nên quá phức tạp; vì vậy tôi nghĩ tốt hơn là đi theo hướng như Rescript hay Gleam, tức là đặt ra một số giới hạn trên ngôn ngữ đích rồi dùng hệ thống kiểu Hindley–Milner. Hệ thống kiểu HM đã tích lũy rất nhiều kinh nghiệm và lý thuyết qua thời gian nên vừa vững vừa thực dụng. Cá nhân tôi thấy khá ngạc nhiên khi không có một dự án ngôn ngữ họ ML nhỏ nào xuất Lua. Nếu Gleam hỗ trợ backend Lua thì có lẽ sẽ rất hợp
    • Đã có dự án như vậy rồi: TypeScriptToLua. Tôi từng dùng với Love2D và thấy khá ổn