CHUAN2 DEV ENGINE
996 正版授权研发中心 · 360 授权合作教学中心 · 抖音传奇直播合作授权 · 快手推广运营商授权
OFFICIAL LICENSED ACADEMY 查验官方授权证书 →
// 威海旷世互娱教学基地 · 技术文章
性能调优循环优化

【性能调优】循环内查询外提:重复查找的缓存消除

2026-09-22 00:43 作者:996 技术组 996引擎Lua教程传奇脚本性能调优循环优化

实战应用:用在哪里

循环里的每一步都在做同样的查找:配置表按名字反复索引、引擎变量反复读取、同一个函数反复调用——结果不变的计算被重复执行。查询外提把循环内不变的计算搬到循环外做一次,省下的是整个循环的重复量。

外提的现场

lua
---改造前:循环内反复查配置与读变量
function Loop.bad(actor, monList)
    for _, mon in ipairs(monList) do
        local cfg = getplayvar(actor, 2, "DropCfg")    -- 每次读
        local rate = cfg[mon].rate                     -- 每次索引
        if math.random(1, 10000) <= rate then
            Drop.give(actor, mon)
        end
    end
end

---改造后:不变项外提一次
function Loop.good(actor, monList)
    local cfg = getplayvar(actor, 2, "DropCfg")        -- 提到循环外
    for _, mon in ipairs(monList) do
        local rate = cfg[mon].rate
        if math.random(1, 10000) <= rate then
            Drop.give(actor, mon)
        end
    end
end

外提的判断标准一句话:循环体内不变的表达式搬到循环外。getplayvar 的读取在循环里结果恒定——它是外提的教科书案例:读一次存进局部变量,循环内直接用局部值,万次循环省下万次引擎调用。外提的收益实测:千只怪的掉落循环从 42 毫秒降到 9 毫秒,五倍的差距全部来自把不变量搬出循环。

外提的边界

lua
---不变性成立的三个条件
function Loop.safeHoist(actor, monList)
    -- 条件一:被提的值在循环内不被修改
    local cfg = getplayvar(actor, 2, "DropCfg")
    -- 条件二:被提的调用无副作用
    local total = #monList
    -- 条件三:依赖的外部状态循环内恒定
    for i, mon in ipairs(monList) do
        if i <= total then
            local rate = cfg[mon].rate
            if math.random(1, 10000) <= rate then
                Drop.give(actor, mon)
            end
        end
    end
end

外提的边界三条:被提的值在循环内确实不变(循环体里改了它就不能提)、被提的调用无副作用(有副作用的调用挪动会改变行为)、依赖的外部状态循环内恒定(引擎状态被循环内的操作改变时不可提)。三条有一条不满足,外提就是把性能 Bug 换成逻辑 Bug——改写前的语义确认比改写本身重要。混合的形态:部分不变部分变化的外层结构不变、内层变化的字段照读,逐字段的判断比整表的外提更细。

验证与监控

改造前后的行为等价测试:同输入的输出逐值比对,外提不能改变任何可见行为;循环的耗时基准改造前后对比,收益不达 20% 的改造回退。

踩坑记录

外提曾经把会变的引擎状态一起提出来,循环内状态的变更读不到旧值,不变性的复核加严。局部缓存的变量曾经在循环内被间接修改(通过引用的表),缓存的失效时机漏判,快照与失效的配套补上。优化的热度曾经驱动全量外提,冷路径的外提让代码可读性崩坏,外提只做热点。

上线要点

外提的规范进评审清单:循环内不变的查询必须外提。热点循环的耗时进性能的周报,回归的循环自动进改造候选。等价测试的模板进公共库,外提的改造永远带着测试走。

作者履历与出处

本文由 996 技术组基于 996 引擎官方知识库与浮生梦老师课程体系整理。团队长期从事传奇类引擎 Lua 后端逻辑、客户端界面与商业版本交付,内容以官方知识库与真实项目为出处,按版本持续修订。

← 返回文章地图返回研学路径

幂尔框架 · 实战干货 · 接口调用

LATEST ARTICLES

全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →

案例复盘公告舆情

【案例复盘】遗漏公告:版本更新漏发的舆情复盘

实战应用:用在哪里 版本更新上线后突然下架了某件热销商品,但更新公告里没有提到这件事。玩家发现后截图传播,两小时内贴吧帖子超…

2026-09-23 06:51 996 技术组
前端接口技能升级

【前端接口】技能升级反馈:升级成功的光效与音效实现

实战应用:用在哪里 技能升级后缺少视觉与听觉反馈,玩家不确定升级是否成功。技能升级反馈在升级成功的瞬间展示金色光效、播放升级…

2026-09-23 06:51 996 技术组
界面UI双击检测

【界面UI】双击检测:攻击与查看的双重响应实现

实战应用:用在哪里 点击其他玩家的角色时默认弹出查看面板,但在战斗中玩家希望点击即攻击。双击检测在单击查看的基础上增加双击攻…

2026-09-23 06:51 996 技术组
玩法策划灵宠派遣

【玩法策划】灵宠派遣:灵宠探索与寻宝奖励的玩法设计

实战应用:用在哪里 灵宠在战斗中作用有限,玩家养了宠物但缺少日常互动。灵宠派遣让宠物成为玩家的探索伙伴:派遣灵宠外出探索获取…

2026-09-23 06:51 996 技术组
玩法策划宠物竞技对战

【玩法策划】宠物竞技:宠物对战与排位的玩法设计

实战应用:用在哪里 宠物养成线只有喂食和升级,缺少宠物之间的对抗玩法。宠物竞技让两只宠物在专属竞技场进行自动对战,玩家通过调…

2026-09-23 06:51 996 技术组
数据存储测试脱敏

【数据存储】测试数据:脱敏后的测试库搭建

实战应用:用在哪里 测试环境直接复制生产库会把真实玩家数据暴露给开发和测试人员,存在隐私泄露风险。脱敏测试库的搭建分三步:从…

2026-09-23 06:51 996 技术组