-
Notifications
You must be signed in to change notification settings - Fork 172
HotFix
Bruce edited this page Feb 25, 2023
·
2 revisions
lua作为脚本语言,一个优势就是可以做热更新,在不重启进程的情况下,用新版本的函数替换旧版本函数。但由于lua的灵活性,实现100%的热更又不太可能。可以参考 https://blog.codingnow.com/2016/11/lua_update.html, 但云风的方案是尽量实现正确的热更,遍历了几乎整个VM,导致处理速度较慢,对于一个玩家一个luaVM的情况下,上千个luaVM可能导致卡顿几分钟。
在一定的限制条件下并兼顾性能,moon提供了一种热更方案,用于修复少量bug的情况:
按模块来更新(一个lua脚本文件),只处理模块内部定义的函数,提高处理速度。
- 模块定义需要复合规范,最后返回
return M
- 模块内不能新增函数
- 新旧版本函数的upvalue个数需要一样,并且引用的upvalue也需要一样
- 无法更新被保存到其他模块的函数
热更处理行为:
- 非函数类型upvalue保留旧版本
- 函数类型的upvalue替换为新版本
- 模块的函数替换为新版本
- 热更是使用新函数替换旧函数,会首先让全部新函数关联旧函数的upvalue,如果中间流程出错,不会影响到原有逻辑。
local moon = require("moon")
---case 1: 非函数类型upvalue
local a = 100
local b = 200
local switch = {}
--case 2:table类型的upvalue, 要求table的value都是function类型(__index除外)
switch[1] = function()
moon.warn("f1", b)
end
---模块的定义
local M = {}
M.__index = M
--case 3:
function M.new()
local obj = {
n = 0,
m = "hello"
}
return setmetatable(obj,M)
end
--case 3:
local function tmp(self)
self.n=self.n+1000+a
end
--case 3:
function M:func()
switch[1]()
tmp(self)
print("before", self.n, self.m, a-b)
moon.sleep(1000)
end
---需要返回模块
return M