Skip to content
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也需要一样
  • 无法更新被保存到其他模块的函数

热更处理行为:

  1. 非函数类型upvalue保留旧版本
  2. 函数类型的upvalue替换为新版本
  3. 模块的函数替换为新版本
  4. 热更是使用新函数替换旧函数,会首先让全部新函数关联旧函数的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
Clone this wiki locally