Với việc hỗ trợ tạo mã gốc Luau, các script phía máy chủ trong trò chơi của bạn có thể được biên dịch trực tiếp thành các lệnh mã máy mà CPU thực thi, thay vì mã bytecode thông thường mà VM Luau hoạt động trên đó. Tính năng này có thể được sử dụng để cải thiện tốc độ thực thi cho một số script trên máy chủ, đặc biệt là những script có nhiều tính toán số mà không sử dụng quá nhiều các thư viện Luau nặng hoặc các cuộc gọi API Roblox.
Bật tạo mã gốc
Để bật tạo mã gốc cho một Script, hãy thêm chú thích --!native ở đầu:¹
--!nativeprint("Xin chào từ mã gốc!")
Điều này kích hoạt tạo mã gốc cho tất cả các hàm trong script, và phạm vi cấp cao nhất, nếu được coi là có lợi. Không cần thay đổi thêm; hành vi của các script thực thi ở dạng mã gốc vẫn hoàn toàn giống như trước đây và chỉ có hiệu suất là khác biệt. Tất cả các tính năng của ngôn ngữ Luau và tất cả các API Roblox vẫn được hỗ trợ.
Ngoài ra, bạn có thể bật tạo mã gốc cho một hàm riêng lẻ bằng cách thêm thuộc tính @native:
@native
local function f(x)
return (x + 1)
end
Các thực hành tốt nhất
Các mẹo sau đây sẽ giúp bạn hưởng lợi nhiều nhất từ việc tạo mã gốc:
Tốt nhất là bật tính năng này bên trong các script mà thực hiện nhiều tính toán trực tiếp trong Luau. Nếu bạn có nhiều phép toán toán học trên các bảng và đặc biệt là các loại buffer, script có thể là ứng cử viên tốt.
Khuyến nghị bạn nên đo thời gian mà một script hoặc một hàm mất với và không có biên dịch mã gốc để đánh giá khi nào nên sử dụng nó. Công cụ Script Profiler có thể đo hiệu suất của các hàm để đưa ra quyết định thông minh.
Có thể bạn sẽ cảm thấy cám dỗ khi đặt chú thích --!native trong mỗi script chỉ để phòng trường hợp một số trong số chúng sẽ thực thi nhanh hơn, nhưng việc tạo mã gốc có một số nhược điểm:
- Thời gian biên dịch mã là cần thiết, điều này có thể làm tăng thời gian khởi động của các máy chủ.
- Bộ nhớ bổ sung được chiếm để lưu trữ mã được biên dịch thành mã gốc.
- Có giới hạn về tổng số mã được biên dịch thành mã gốc được phép trong một trò chơi.
Những vấn đề này có thể được giải quyết bằng cách sử dụng hợp lý thuộc tính @native.
Mã không nên sử dụng
Mặc dù tất cả các tính năng sẽ hoạt động giống nhau với hoặc không có tạo mã gốc được bật, nhưng một số trong số chúng sẽ không chạy ở dạng mã gốc và có thể gây ra de-optimization hoặc rơi về thực thi được giải thích. Những điều này bao gồm:
- Sử dụng các hàm tích hợp sẵn của Luau như math.asin() với các đối số phi số.
- Truyền các tham số có kiểu không đúng cho các hàm có kiểu, ví dụ gọi foo(true) khi foo được khai báo là function foo(arg: string). Nhớ luôn sử dụng các chú thích kiểu đúng.
Khi sử dụng Script Profiler, bạn có thể so sánh thời gian mà phiên bản thông thường của hàm so với phiên bản đã biên dịch thành mã gốc. Nếu một hàm bên trong script --!native hoặc được đánh dấu với @native không xuất hiện là đang thực thi bằng mã gốc, một hoặc nhiều yếu tố từ danh sách trên có thể kích hoạt de-optimization.
Sử dụng chú thích kiểu
Tạo mã gốc sẽ cố gắng suy diễn kiểu có khả năng nhất cho một biến nhất định để tối ưu hóa các đường dẫn mã. Ví dụ, nó được giả định rằng a + b được thực hiện trên các số, hoặc rằng một bảng được truy cập trong t.X. Tuy nhiên, với việc quá tải toán tử, a và b có thể là các bảng hoặc các loại Vector3, hoặc t có thể là một loại dữ liệu Roblox.
Trong khi tạo mã gốc sẽ hỗ trợ bất kỳ kiểu nào, những dự đoán sai có thể kích hoạt các kiểm tra không cần thiết, dẫn đến việc thực thi mã chậm hơn.
Để giải quyết một số vấn đề phổ biến, các chú thích kiểu Luau trên các tham số hàm được kiểm tra, nhưng đặc biệt khuyến nghị ghi chú các tham số Vector3:
--!native
-- "v" được giả định là một bảng; hàm thực thi chậm hơn do các kiểm tra bảng
local function sumComponentsSlow(v)
return v.X + v.Y + v.Z
end
-- "v" được khai báo là một Vector3; mã chuyên biệt cho các vector được tạo ra
local function sumComponentsFast(v: Vector3)
return v.X + v.Y + v.Z
end
Công cụ Studio
Các công cụ Studio sau đây được hỗ trợ cho các script --!native và các hàm @native.
Gỡ lỗi
Việc gỡ lỗi chung của các script được hỗ trợ, nhưng các chế độ xem cho các biến cục bộ/upvalues có thể không hoàn chỉnh và thiếu biến từ các khung ngăn xếp gọi đang thực thi ở dạng mã gốc.
Cũng lưu ý rằng khi gỡ lỗi mã được chọn để biên dịch thành mã gốc, việc đặt điểm dừng sẽ vô hiệu hóa việc thực thi mã gốc cho những hàm đó.
Script Profiler
Trong Script Profiler, các hàm thực thi ở dạng mã gốc hiển thị <native> bên cạnh chúng:

Nếu một hàm được đánh dấu @native hoặc ở bên trong script --!native không hiển thị dấu hiệu <native>, hàm đó có thể không thực thi ở dạng mã gốc do việc đặt điểm dừng, sử dụng mã không được khuyến nghị, hoặc các chú thích kiểu không khớp.
Heap Luau
Trong bộ gỡ lỗi Luau heap, bộ nhớ được sử dụng bởi các hàm gốc hiển thị dưới dạng các thành phần [native] trong biểu đồ.

Phân tích kích thước
Mỗi script được biên dịch thành mã gốc đều tiêu thụ bộ nhớ. Khi kích thước của mã biên dịch đạt giới hạn đã định sẵn, việc biên dịch mã gốc dừng lại và mã còn lại được chạy không ở dạng mã gốc. Điều này làm cho việc lựa chọn các script cẩn thận cho việc biên dịch thành mã gốc là rất quan trọng.
Để theo dõi kích thước mã gốc của các hàm và script cá nhân:
- Đảm bảo bạn đang ở chế độ Server thông qua nút chuyển đổi client/server.
- Gọi debug.dumpcodesize() từ Command Bar.
Trong cửa sổ Output, bạn sẽ thấy tổng số script và hàm đã được biên dịch thành mã gốc tại thời điểm gọi, bộ nhớ tiêu thụ bởi mã gốc của chúng, và giới hạn kích thước mã gốc. Sau tóm tắt, bạn sẽ thấy một bảng cho mỗi script được biên dịch thành mã gốc theo thứ tự giảm dần của kích thước mã.

Đối với mỗi script, đầu ra hiển thị số lượng hàm đã biên dịch và mức tiêu thụ bộ nhớ mã gốc. Mỗi hàm sau đó được liệt kê theo thứ tự giảm dần của kích thước mã gốc, với các hàm ẩn danh được hiển thị là [anonymous] và toàn bộ scripts được hiển thị là [top level]. Trong cột cuối cùng, tỷ lệ phần trăm được tính toán liên quan đến giới hạn kích thước mã gốc. Lưu ý rằng kích thước mã gốc của các hàm được báo cáo chính xác nhưng mức tiêu thụ bộ nhớ cho các script được làm tròn lên đến kích thước trang gần nhất.
Giới hạn và khắc phục sự cố
Việc biên dịch mã thành các lệnh cho một CPU cụ thể yêu cầu bộ nhớ lưu trữ bổ sung. Ngoài ra, các tối ưu hóa cho các hàm phức tạp có thể mất quá nhiều thời gian để thực hiện. Việc đạt được giới hạn nội bộ sẽ báo cáo một lỗi trong cửa sổ Output của Studio, bao gồm:
Hàm 'f' tại dòng 20 đã vượt quá giới hạn lệnh khối mã đơn
Lỗi này có nghĩa là một khối mã trong hàm sử dụng hơn 64K lệnh. Điều này có thể tránh được bằng cách đơn giản hóa hàm hoặc chia nó thành các hàm nhỏ hơn riêng lẻ.
Hàm 'f' tại dòng 20 đã vượt quá giới hạn khối mã hàm
Lỗi này có nghĩa là một hàm đơn chứa hơn 32K khối mã nội bộ. Các khối mã nội bộ không đồng nhất với các khối điều khiển luồng trong script của bạn, nhưng lỗi này có thể được tránh bằng cách đơn giản hóa luồng điều khiển trong hàm hoặc chia nó thành các hàm nhỏ hơn riêng lẻ.
Hàm 'f' tại dòng 200 đã vượt quá tổng giới hạn lệnh module
Lỗi này có nghĩa là, tổng thể, hàm đã đạt tới giới hạn 1 triệu lệnh cho toàn bộ script. Trong một số trường hợp, hàm được báo cáo có thể có nhiều lệnh, hoặc giới hạn có thể đã được đạt bởi các hàm trước đó trong script. Để tránh vấn đề này, khuyến nghị bạn nên di chuyển các hàm đặc biệt lớn vào một script không phải mã gốc riêng biệt hoặc sử dụng @native trên các hàm khác. Bạn cũng có thể thử đánh dấu script riêng biệt đó với --!native, nhưng 1 triệu lệnh tiêu tốn nhiều bộ nhớ và bạn có thể vượt quá giới hạn bộ nhớ.
Hàm 'f' tại dòng 20 gặp phải lỗi hạ cấp nội bộ (hoặc)
Lỗi nội bộ: Tạo mã gốc đã thất bại (hạ cấp lắp ráp)
Đôi khi một hàm chứa các đoạn mã phức tạp mà trình biên dịch mã gốc không thể xử lý hiện tại. Để tránh lỗi này, hãy kiểm tra các biểu thức phức tạp trong mã và chia nhỏ chúng hoặc đơn giản hóa chúng, nhưng cũng hãy xem xét việc mở một báo cáo lỗi với một ví dụ về mã đã thất bại vì lý do này.
Giới hạn phân bổ bộ nhớ đã đạt cho việc tạo mã gốc
Lỗi này có nghĩa là giới hạn bộ nhớ tổng thể cho dữ liệu mã gốc đã đạt đến. Để tránh điều này, hãy thử loại bỏ --!native từ các script tốn bộ nhớ hơn, cho phép nhiều script nhỏ hơn vừa vặn dưới giới hạn. Ngoài ra, di chuyển các hàm lớn hoặc ít được gọi đến một mô-đun không phải mã gốc riêng biệt.