lua脚本解析支持预编译缓存

This commit is contained in:
白茶清欢 2025-05-12 15:36:46 +08:00
parent 8ad636517b
commit b44b7945b8

69
vm.go
View File

@ -8,7 +8,11 @@
package lua
import (
"fmt"
luaCompile "github.com/yuin/gopher-lua"
"github.com/yuin/gopher-lua/ast"
"github.com/yuin/gopher-lua/parse"
"strings"
"sync"
)
@ -16,19 +20,57 @@ var (
VMInstance *VM
)
func InitVM(poolSize int) {
// InitVM 初始化lua虚拟机
func InitVM(poolSize int, preComplierScript map[string]string) error {
if poolSize <= 0 {
poolSize = 32
}
VMInstance = &VM{
l: &sync.RWMutex{},
scriptLock: &sync.RWMutex{},
pool: make([]*luaCompile.LState, 0),
preComplierScript: make(map[string]*luaCompile.FunctionProto),
}
for scriptID, scriptContent := range preComplierScript {
if err := VMInstance.AddScript(scriptID, scriptContent); nil != err {
return err
}
}
return nil
}
type VM struct {
l *sync.RWMutex
pool []*luaCompile.LState
scriptLock *sync.RWMutex
pool []*luaCompile.LState // lua虚拟机实例池
preComplierScript map[string]*luaCompile.FunctionProto // 预编译的脚本内容
}
// AddScript 脚本编译
func (v *VM) AddScript(scriptID string, script string) error {
v.scriptLock.Lock()
defer v.scriptLock.Unlock()
var (
err error
chunk []ast.Stmt
proto *luaCompile.FunctionProto
)
if chunk, err = parse.Parse(strings.NewReader(script), scriptID); nil != err {
return err
}
if proto, err = luaCompile.Compile(chunk, scriptID); nil != err {
return err
}
v.preComplierScript[scriptID] = proto
return nil
}
// RemoveScript 删除一个已编译的脚本
func (v *VM) RemoveScript(scriptID string) {
v.scriptLock.Lock()
defer v.scriptLock.Unlock()
delete(v.preComplierScript, scriptID)
}
// GetVm 获取一个VM实例
@ -59,6 +101,29 @@ func (v *VM) Shutdown() {
}
}
// RunPreCompileScript 执行预编译过的脚本
func (v *VM) RunPreCompileScript(scriptID string) (*luaCompile.LState, error) {
var (
err error
proto *luaCompile.FunctionProto
exists bool
)
v.scriptLock.Lock()
if proto, exists = v.preComplierScript[scriptID]; !exists {
v.scriptLock.Unlock()
return nil, fmt.Errorf("preComplier script %s not found", scriptID)
}
v.scriptLock.Unlock()
l := v.GetVm()
lFunc := l.NewFunctionFromProto(proto)
l.Push(lFunc)
if err = l.PCall(0, luaCompile.MultRet, nil); nil != err {
v.Close(l)
return nil, err
}
return l, nil
}
// Run 运行脚本
//
// Author : go_developer@163.com<白茶清欢>