通过 Luau 支持对本地代码生成,您的体验中的服务器端脚本可以直接编译为机器代码指令,而不是 Luau VM 运行的常规字符码。该功能可用于提高服务器上某些脚本的执行速度,特别是那些没有使用太多重型 Luau 库或 Roblox API 调用的数值计算的脚本。
启用本地代码生成
要启用对 的本地代码生成,请在顶部添加 评论:¹
--!原生print("Hello from native code!")
这可以启用脚本中所有函数的本地代码生成,以及最高级范围,如果觉得有利可图。无需进行额外更改;以 natively 执行的脚本的行为与之前相同,只有性能不同。Luau 语言的所有功能和所有 Roblox API 仍然受支持。
或者,您可以通过添加 @native 属性来启用单个函数的本地代码生成:
@native
local function f(x)
return (x + 1)
end
最佳实践
以下提示将帮助您最大限度地从原生代码生成中受益:
最好在 Luau 内直接执行大量计算的脚本中启用此功能。如果您有很多数学操作在表和特别是 buffer 类型上,脚本可能是一个好候选人。
建议您测量脚本或函数的执行时间,包括使用本地编译时间和无使用本地编译时间,以判断何时最好使用它。脚本调试工具可以测量函数的性能,以便做出明智的决定。
可能有诱惑将 --!native 评论放在 每个 脚本中,只是为了防止一些更快地执行,但原生代码生成有一些缺点:
- 需要编译代码的时间,可以增加服务器的启动时间。
- 额外的内存用于存储 natively 编译的代验证码。
- 体验中的 natively 编译代码的总允许数量有限。
这些问题可以通过合理使用 @native 属性来解决。
需要避免的代码
虽然所有功能都会在启用本地代码生成或无启用本地代码生成时与或无关,但其中一些功能不会运行原生,可能会导致优化降级或回到解释执行。这些包括:
- 使用 Luau 内置功能(例如 math.asin() )与非数字参数一起使用各种功能。
使用 脚本调试器 时,您可以比较函数的常规版本与编译为原生的版本之间的时间。如果在 --!native 脚本中的函数或标记为 @native 不会自动运行,上面的列表中的一个或多个因素可能会触发反优化。
使用类型注释
本地代码生成尝试通过推测给定变量的最可能类型来优化代码路径。例如,假设 a + b 在数字上执行,或者表在 t.X 中访问。然而,由于操作符过载,a 和 b 可能是表或 Vector3 类型,或 t 可能是 Roblox 数据类型。
虽然本地代码生成支持任何输入,但预测错误可能会触发不必要的检查,导致代码执行速度降低。
为了解决一些常见问题,Luau 类型的注释对函数参数进行检查,但特别建议对 Vector3 参数进行注释:
--!原生
-- “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
end
工作室工具
以下工作室工具支持 --!native 脚本和 @native 函数。
调试
支持脚本的一般 调试,但本地/上值的视图可能不完整且缺少从 调用堆栈 框中执行的变量。
请注意,当调试选定的原生编译代码时,放置 断点 会禁用这些函数的原生执行。
脚本调试器
在 脚本调试器 中,执行本地函数会显示它们旁边的 <native>:

如果一个函数标记了 或在 脚本内部显示了 标记,那个函数可能不会以原生方式运行,因为由于 断点放置 、使用了 被禁止代码 或匹配不上的 类型标记 。
Luau堆
在 Luau 堆 调试器中,由本地函数占用的内存显示为图表中的 [native] 元素。

尺寸分析
每个默认编译的脚本都消耗内存。当编译代码的大小达到预定义限制时,本地编译停止,剩余的代码运行不支持。这使得选择本地编译的脚本非常重要。
要监控单个函数和脚本的原生代码大小:
在 输出 窗口中,你会看到到召回点为止已经 natively 编译的脚本和函数总数、由其本地代验证码消耗的内存以及本地代码大小限制。在摘概括之后,你会看到一个表,其中包含每个默认编译的脚本的代码规模从大到小的排序。

对于每个脚本,输出显示编译的函数数量和本地代码存储消耗量。然后,每个函数按照原生代码大小的降序排列,匿名函数显示为 [anonymous] ,整个脚本显示为 [top level] 。在最后一列中,百分比与原生代码大小限制相关。请注意,函数的本地代码大小精确报告,但脚本的内存消耗会被圆到最接近的页面大小。
限制和排除故障
将代码编译为特定 CPU 的指令需要额外的存储内存。此外,对复杂函数的优化可能需要太长时间来执行。击中内部限制将在 Studio 的 输出 窗口报告错误,包括:
函数 'f' 在第 20 行超过了单个代码块指令限制
这个错误意味着函数内的单个代码块使用了超过 64K 个指令。这可以通过简化函数或将其分解为更小的单个函数来避免。
函数 'f' 在第 20 行超过了函数代码块限制
这个错误意味着单个函数包含超过 32K 内部代验证码块。代码内部块与脚本中的控制流块不完全匹配,但这个错误可以通过简化函数中的控制流或将其分解为更小的单个函数来避免。
函数 'f' 在第 200 行超过了总模块指令限制
这个错误意味着,在总计,函数已达到整个脚本的 100 万条指令的限制。在一些情况下,报告的函数本身可能有很多指令,或限制可能已由脚本中的更早函数达到。为了避免这个问题,建议将特别大的函数移至单独的非本地脚本或使用 @native 在其他函数上。您还可以尝试使用 --!native 来标记那个单独的脚本,但 100 万条指令占用大量内存,您可能会超过内存限制。
在第 20 行的函数 'f' 遇到了内部降级失败 (或) 内部错误:原生代码生成失败(组装降级)
有时函数包含复杂的代码片段,现有的本地代码编译器无法处手柄。为了避免这种错误,在代码中检查复杂的表达式,分开或简化它们,但也考虑打开一个错误报告,带有这个原因失败的代码的示例。
达到了对原生代码生成的内存分配限制
这个错误意味着已达到原生代码数据的整体内存限制。为了避免这种情况,请尝试从更多资源密集的脚本中删除 --!native ,以允许更多更小的脚本适合限制。或者,将大或不常调用的函数移至单独的非本地模块。