关于 luau-performance
luau-performance 面向需要优化 Luau 运行时性能的开发者。它强调先分析并确认热点,再减少重复工作和分配,同时兼顾运行时快速路径与代码可维护性。
主要功能
- 01分析并确认运行时热点
- 02降低分配与垃圾回收压力
- 03选择表与迭代方式
- 04保留内置函数和编译器快速路径
- 05查阅分析与运行时参考资料
适用场景
- 01排查经测量确认的 Luau 慢函数
- 02减少频繁执行代码中的分配
- 03调整热点路径的表访问与迭代
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ luumenlabs/ luau-skills --skill luau-performance安装后在 Claude Code 中输入/luau-performance确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/library-performance-sensitive-patterns.mdluau-performance-guide.mdprofiling-guide.mdruntime-and-compiler-optimization-notes.mdsandbox-constraints-relevant-to-runtime-behavior.md详细介绍
luau-performance
适用场景
当任务主要涉及 Luau 运行时开销时,使用此技能:
- 在更改实现细节前分析代码,找出真正的性能热点。
- 减少重复路径中的分配 churn、GC 压力或闭包创建。
- 选择更快的表构建、查找、追加和迭代模式。
- 让代码能够利用 Luau 对内置函数调用、方法调用和导入的快速路径。
- 解释编译器和运行时优化对热点函数的影响。
- 在兼顾可读性和可维护性的同时,调优已确认的热点路径。
- 仅当沙箱或环境行为会改变 Luau 的执行方式或导致代码反优化时,才将其纳入考虑。
当任务主要涉及以下内容时,请勿使用此技能:
- 从基础开始讲解 Luau 语法、控制流、表或元表。
- 设计复杂的类型系统抽象、分析器行为或高级类型工具。
- Roblox 特有的复制、流式加载、渲染、网络、物理或其他引擎性能模式。
决策规则
- 从测量开始。如果代码并非简单代码,在声称优化有效之前,先进行性能分析或基准测试。
- 优先解决算法开销,再微调字节码级细节。
- 优先选择能够减少热点路径中重复工作、重复分配或重复动态分派的改动。
- 让对性能敏感的模块运行在纯净环境中。需要速度时,避免使用
getfenv、setfenv和loadstring。 - 在热点代码中优先使用稳定的表结构、直接字段访问、直接调用内置函数和简单的调用图。
- 仅在测量表明可能有效且运行时确实支持时,才使用特定于环境的编译功能。
- 如果任务转为讲解核心语言,请使用
luau-core。 - 如果任务主要转为讨论类型、推断或注解,请使用
luau-types。 - 如果任务依赖的是 Roblox 引擎架构,而非 Luau 执行行为,请转交给相应的
roblox/*技能。 - 如果请求将性能优化与范围外主题混在一起,只回答 Luau 运行时相关部分,并排除其余内容。
说明
- 首先明确工作负载:
- 哪些操作经常运行;
- 哪些操作经常分配内存;
- 什么处于关键路径上;
- 最重要的指标是什么:耗时、帧预算还是内存抖动。
- 重写前先分析性能。使用采样或环境工具,找出实际主导运行时间的函数。
- 优先优化经验证的最大瓶颈。不要在冷代码中分散进行微优化。
- 减少重复路径中的分配压力:
- 避免每次迭代都重新构建表;
- 除非确有必要,否则避免在循环中创建新的闭包;
- 避免保留表或连接超过所需时间。
- 根据运行时特性组织表:
- 使用字面量创建类对象表,并一次性提供所有已知字段;
- 在多次调用之间保持对象布局一致;
- 仅对已知容量的类数组表使用
table.create。
- 有意识地选择迭代方式:
- 遍历普通表时使用泛型迭代
for k, v in t do; - 仅在需要遇到第一个
nil就停止时使用ipairs; - 需要索引本身或算法涉及顺序写入时,使用数值循环。
- 遍历普通表时使用泛型迭代
- 让内置函数的快速路径一目了然:
- 直接调用内置函数,例如
math.max(x, y)或string.byte(s, 1); - 不要通过不必要的间接调用来隐藏热点内置函数调用;
- 快速调用行为取决于调用形式时,优先使用内置函数形式而非方法形式。
- 直接调用内置函数,例如
- 让调用点对编译器友好:
- 热点辅助函数优先使用
local function; - 避免不必要地修改被捕获的值;
- 将小型辅助函数保留在模块内,以便更好地内联。
- 热点辅助函数优先使用
- 让热点代码中的元表开销保持低廉:
- 将数据存储在对象本身;
- 让
__index直接指向一个表; - 避免在关键路径上使用
__index函数和深层查找链。
- 将环境特性视为性能约束:
getfenv、setfenv和loadstring可能导致导入和内置函数快速处理失去优化;- 在某些环境中,调试和断点可能改变观察到的运行时行为;
- 在支持原生编译的情况下,应有选择地应用并进行测量。
- 注重实用性。优先采用能消除可测量开销的最简单改动,即使更激进的重写理论上速度更快。
使用参考资料
- 打开
references/luau-performance-guide.md,了解 Luau 快速路径的主要模型:表访问、导入、方法调用、迭代和注重分配的表构建。 - 打开
references/profiling-guide.md,了解分析器工作流、火焰图解读、用于归因的函数命名方式,以及特定环境下的性能分析说明。 - 打开
references/runtime-and-compiler-optimization-notes.md,了解编译器限制、内联、常量折叠、上值、闭包缓存和选择性原生编译指南。 - 打开
references/library-performance-sensitive-patterns.md,了解有关math、string、table、迭代辅助函数和面向数组的 API 的实用选择。 - 打开
references/sandbox-constraints-relevant-to-runtime-behavior.md,了解会禁用或削弱运行时优化的环境规则。 - 除非任务明确涉及其他技能的范围,否则不要打开其他技能参考资料。
检查清单
- 对所声称的热点,已有测量计划或分析器结果。
- 拟议改动针对的是运行频率足以产生影响的路径。
- 在微调语法之前,已考虑算法成本。
- 在重复执行的代码中减少了分配抖动。
- 表的形态和迭代策略与数据模式相匹配。
- 在可能的情况下,内置函数调用足够直接,以保留快速路径。
- 热点模块中避免使用
getfenv、setfenv或loadstring等会导致环境优化失效的函数。 - 任何特定于环境的编译功能都有测量依据,而非凭猜测采用。
- 指南仅涉及 Luau 执行行为,不涉及 Roblox 引擎性能主题。
常见错误
- 因为代码“看起来很耗时”,就优化未经测量的代码。
- 用
table.create创建字典,而不是数组。 - 以为
pairs或ipairs一定比通用迭代更快。 - 即使 Luau 已经能很好地优化方法调用,仍将
obj:Method()改写为缓存方法的局部变量。 - 在热点路径上用封装函数或间接分发来隐藏内置函数调用。
- 频繁改变对象表的键,却期望字段查找缓存仍然有效。
- 只用
getfenv读取环境,却以为它不会带来优化成本。 - 到处添加原生编译指令,却不测量内存、启动时间或实际运行时收益。
示例
预分配数组并按顺序填充
local function buildSquares(count)
local result = table.create(count)
for i = 1, count do
result[i] = i * i
end
return result
end
在热点代码中直接调用内置函数
local function clamp01(x)
return math.min(math.max(x, 0), 1)
end
使用稳定的对象布局和直接的 __index
local Counter = {}
Counter.__index = Counter
function Counter.new(step)
return setmetatable({
value = 0,
step = step,
}, Counter)
end
function Counter:advance()
self.value += self.step
return self.value
end
避免在对性能敏感的模块中使环境优化失效
local function magnitude2(x, y)
return math.sqrt(x * x + y * y)
end
return magnitude2
评论
支持 Markdown