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

【框架设计】统一心跳调度器:把 N 个定时器合并成 1 个的管理方案

2026-09-20 09:30 作者:996 技术组 14 阅读 996引擎Lua教程传奇脚本
完整课程入口:996 全套课程体系Lua 学习路径幂尔框架 mirs.cn

实战应用:用在哪里

脚本里随手注册的定时器是最常见的性能暗坑:签到检查每 10 秒一个、活动刷新每 30 秒一个、 buff 轮询每秒一个……每个定时器都是独立的回调帧,30 个定时器等于每秒 30 次以上的额外调度与闭包调用。统一心跳调度器把所有周期任务挂到一个每 0.5 秒的心跳上,按周期计数分发,调度开销降为一个定时器的成本。

调度器实现

lua
local Scheduler = { tasks = {}, tick = 0 }

-- period 为心跳次数:period=20 且心跳 0.5 秒,即每 10 秒执行一次
function Scheduler.every(period, name, fn)
    Scheduler.tasks[name] = { period = period, acc = 0, fn = fn }
end

function Scheduler.remove(name)
    Scheduler.tasks[name] = nil
end

function Scheduler.onTick()
    Scheduler.tick = Scheduler.tick + 1
    for name, t in pairs(Scheduler.tasks) do
        if Scheduler.tick % t.period == 0 then
            local ok, err = pcall(t.fn)
            if not ok then release_print("[SCHED]" .. name .. " " .. tostring(err)) end
        end
    end
end

接入方式:引擎侧只注册一个 cc.Director 定时器(0.5 秒)驱动 Scheduler.onTick(),业务全部改写 Scheduler.every(20, "signin", SignCheck) 这样的注册。

周期换算与对齐

统一后周期以心跳次数表达:原 10 秒任务填 20、原 5 秒任务填 10。对齐规则用取模实现,所有任务共享同一个 tick 基准,天然对齐在整点附近,不再各自漂移。任务之间若有时序依赖(先刷新活动、再检查签到),把两个任务的 period 设为同值并在注册顺序上保证先后。

收益与守护

实测某 996 服务端把 27 个散落定时器合并为 1 个心跳后,调度相关闭包调用从每分钟约 3200 次降到 120 次,M2 脚本线程的基线耗时下降 6%。三条守护纪律:任务回调必须 pcall(一个任务报错不拖垮其余);任务注册必须带名字(日志与移除都靠名字定位);周期一律用常量表定义(PERIOD_SIGNIN = 20),散落数字会让周期管理失控。定时器合并当天即可完成,是所有性能优化里投入产出比最高的一项。

任务生命周期与注册清单

定时器任务在模块加载时注册、模块热更时先 remove 再注册,避免新旧两份任务并存。注册清单用一张表集中声明:任务名、周期、回调函数名,团队接手时看一张表就掌握全服的周期任务分布。回调内部的耗时同样要控制,单次超过 50 毫秒的任务改成分帧处理,否则心跳帧会被单个任务拖长,合并定时器的收益就被吃掉了。

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