隨著 Luau 對原生代碼生成的支持,您遊戲中的伺服器端腳本可以直接編譯成 CPU 執行的機器碼指令,而不是 Luau VM 操作的常規字節碼。此功能可用於提高伺服器上某些腳本的執行速度,特別是那些進行大量數值計算而不使用過多重的 Luau 庫或 Roblox API 調用的腳本。
啟用原生代碼生成
要為 Script 啟用原生代碼生成,請在頂部添加 --!native 註解:¹
--!native
print("Hello from native code!")這將為腳本中的所有函數啟用原生代碼生成,並在被認為有利的情況下啟用頂層範圍。無需其他更改;原生執行腳本的行為與之前完全相同,只有性能有所不同。Luau 語言的所有功能和所有 Roblox API 仍然受到支持。
或者,您可以通過添加 @native 屬性來為單個函數啟用原生代碼生成:
@native
local function f(x)
return (x + 1)
end最佳實踐
以下提示將幫助您最大限度地受益於原生代碼生成:
最好在直接在 Luau 中執行大量計算的腳本中啟用此功能。如果您在表格上有大量數學運算,特別是 buffer 類型,則該腳本可能是一個良好的候選者。
建議您測量腳本或函數在啟用和未啟用原生編譯時所需的時間,以判斷何時最好使用它。 腳本分析器 工具可以測量函數的性能,以便做出明智的決策。
可能會有誘惑在每個腳本中放置 --!native 註解,以防其中一些執行得更快,但原生代碼生成有一些缺點:
- 需要代碼編譯時間,這可能會增加伺服器的啟動時間。
- 需要額外的內存來存儲原生編譯的代碼。
- 遊戲中允許的原生編譯代碼的總量有限。
這些問題可以通過明智地使用 @native 屬性來解決。
避免的代碼
雖然所有功能在啟用或未啟用原生代碼生成時的行為相同,但其中一些將不會以原生方式運行,並可能導致去優化或回退到解釋執行。這些包括:
- 使用各種 Luau 內置函數,如 math.asin(),並傳遞非數字參數。
在使用 腳本分析器 時,您可以比較常規版本的函數與原生編譯版本所需的時間。如果在 --!native 腳本或標記為 @native 的函數中未顯示原生執行,則可能是上述列表中的一個或多個因素觸發了去優化。
使用類型註解
原生代碼生成會嘗試推斷給定變量的最可能類型,以優化代碼路徑。例如,假設 a + b 是在數字上執行的,或者在 t.X 中訪問一個表格。然而,考慮到運算符重載,a 和 b 可能是表格或 Vector3 類型,或者 t 可能是 Roblox 數據類型。
雖然原生代碼生成將支持任何類型,但錯誤的預測可能會觸發不必要的檢查,導致代碼執行變慢。
為了解決一些常見問題,Luau 對函數參數的類型註解進行檢查,但特別建議對 Vector3 參數進行註解:
--!native
-- "v" 被假設為一個表;由於表檢查,函數執行較慢
local function sumComponentsSlow(v)
return v.X + v.Y + v.Z
end
-- "v" 被聲明為 Vector3;生成專門針對向量的代碼
local function sumComponentsFast(v: Vector3)
return v.X + v.Y + v.Z
endStudio 工具
以下 Studio 工具支持 --!native 腳本和 @native 函數。
調試
支持腳本的一般 調試,但本地/上值的視圖可能不完整,並且缺少來自執行原生的 調用堆棧 幀的變量。
還要注意,當調試選定為原生編譯的代碼時,放置 斷點 將禁用這些函數的原生執行。
腳本分析器
在 腳本分析器 中,原生執行的函數旁邊顯示 <native>:

如果標記為 @native 或位於 --!native 腳本中的函數未顯示 <native> 註解,則該函數可能因為 斷點 放置、使用 不建議的代碼 或不匹配的 類型註解 而未以原生方式執行。
Luau 堆
在 Luau 堆 分析器中,原生函數佔用的內存顯示為圖表中的 [native] 元素。

大小分析
每個原生編譯的腳本都會消耗內存。當編譯代碼的大小達到預定限制時,原生編譯將停止,剩餘代碼將以非原生方式運行。這使得仔細選擇腳本以進行原生編譯變得至關重要。
要監控單個函數和腳本的原生代碼大小:
在 輸出 窗口中,您將看到在調用時已原生編譯的腳本和函數的總數、它們的原生代碼佔用的內存以及原生代碼大小限制。隨後,您將看到每個原生編譯腳本的代碼大小按降序排列的表格。

對於每個腳本,輸出顯示編譯的函數數量和原生代碼內存消耗。然後按原生代碼大小的降序列出每個函數,匿名函數顯示為 [anonymous],整個腳本顯示為 [top level]。在最後一列中,百分比是相對於原生代碼大小限制計算的。請注意,函數的原生代碼大小報告是精確的,但腳本的內存消耗四捨五入到最接近的頁面大小。
限制和故障排除
將代碼編譯為特定 CPU 的指令需要額外的存儲內存。此外,對複雜函數的優化可能需要花費過多時間。達到內部限制將在 Studio 的 輸出 窗口中報告錯誤,包括:
函數 'f' 在第 20 行超過單個代碼塊指令限制
此錯誤意味著函數內的單個代碼塊使用了超過 64K 的指令。可以通過簡化函數或將其拆分為單獨的小函數來避免此問題。
函數 'f' 在第 20 行超過函數代碼塊限制
此錯誤意味著單個函數包含超過 32K 的內部代碼塊。內部代碼塊並不完全映射到腳本中的控制流塊,但可以通過簡化函數中的控制流或將其拆分為單獨的小函數來避免此錯誤。
函數 'f' 在第 200 行超過總模塊指令限制
此錯誤意味著該函數的總指令數達到了整個腳本的 100 萬指令限制。在某些情況下,報告的函數本身可能有很多指令,或者該限制可能是由腳本中較早的函數達到的。為了避免此問題,建議將特別大的函數移到單獨的非原生腳本中,或在其他函數上使用 @native。您還可以嘗試用 --!native 標記該單獨的腳本,但 100 萬指令佔用大量內存,您可能會超過內存限制。
函數 'f' 在第 20 行遇到內部降低失敗 (或)
內部錯誤:原生代碼生成失敗(組合降低)
有時,函數包含原生代碼編譯器目前無法處理的複雜代碼。為了避免此錯誤,檢查代碼中的複雜表達式並將其拆分或簡化,但也考慮打開錯誤報告,並提供因這個原因失敗的代碼示例。
達到原生代碼生成的內存分配限制
此錯誤意味著原生代碼數據的整體內存限制已達到。為了避免這種情況,請嘗試從內存消耗較大的腳本中刪除 --!native,以便讓更多較小的腳本符合限制。或者,將大型或不經常調用的函數移到單獨的非原生模塊中。