mcpField
L
luau-performance

luau-performance

github.com/luumenlabs开发13201 次安装22 周前更新
代码仓库

关于 luau-performance

luau-performance 面向需要优化 Luau 运行时性能的开发者。它强调先分析并确认热点,再减少重复工作和分配,同时兼顾运行时快速路径与代码可维护性。

主要功能

  1. 01分析并确认运行时热点
  2. 02降低分配与垃圾回收压力
  3. 03选择表与迭代方式
  4. 04保留内置函数和编译器快速路径
  5. 05查阅分析与运行时参考资料

适用场景

  1. 01排查经测量确认的 Luau 慢函数
  2. 02减少频繁执行代码中的分配
  3. 03调整热点路径的表访问与迭代

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/luumenlabs/luau-skills --skill luau-performance

安装后在 Claude Code 中输入/luau-performance确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
library-performance-sensitive-patterns.md
luau-performance-guide.md
profiling-guide.md
runtime-and-compiler-optimization-notes.md
sandbox-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 运行时相关部分,并排除其余内容。

说明

  1. 首先明确工作负载:
    • 哪些操作经常运行;
    • 哪些操作经常分配内存;
    • 什么处于关键路径上;
    • 最重要的指标是什么:耗时、帧预算还是内存抖动。
  2. 重写前先分析性能。使用采样或环境工具,找出实际主导运行时间的函数。
  3. 优先优化经验证的最大瓶颈。不要在冷代码中分散进行微优化。
  4. 减少重复路径中的分配压力:
    • 避免每次迭代都重新构建表;
    • 除非确有必要,否则避免在循环中创建新的闭包;
    • 避免保留表或连接超过所需时间。
  5. 根据运行时特性组织表:
    • 使用字面量创建类对象表,并一次性提供所有已知字段;
    • 在多次调用之间保持对象布局一致;
    • 仅对已知容量的类数组表使用 table.create。
  6. 有意识地选择迭代方式:
    • 遍历普通表时使用泛型迭代 for k, v in t do;
    • 仅在需要遇到第一个 nil 就停止时使用 ipairs;
    • 需要索引本身或算法涉及顺序写入时,使用数值循环。
  7. 让内置函数的快速路径一目了然:
    • 直接调用内置函数,例如 math.max(x, y) 或 string.byte(s, 1);
    • 不要通过不必要的间接调用来隐藏热点内置函数调用;
    • 快速调用行为取决于调用形式时,优先使用内置函数形式而非方法形式。
  8. 让调用点对编译器友好:
    • 热点辅助函数优先使用 local function;
    • 避免不必要地修改被捕获的值;
    • 将小型辅助函数保留在模块内,以便更好地内联。
  9. 让热点代码中的元表开销保持低廉:
    • 将数据存储在对象本身;
    • 让 __index 直接指向一个表;
    • 避免在关键路径上使用 __index 函数和深层查找链。
  10. 将环境特性视为性能约束:
  • getfenv、setfenv 和 loadstring 可能导致导入和内置函数快速处理失去优化;
  • 在某些环境中,调试和断点可能改变观察到的运行时行为;
  • 在支持原生编译的情况下,应有选择地应用并进行测量。
  1. 注重实用性。优先采用能消除可测量开销的最简单改动,即使更激进的重写理论上速度更快。

使用参考资料

  • 打开 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