副问题[/!--empirenews.page--]
在 GitHub 玩耍时,偶尔发明白 gopher-lua ,这是一个纯 Golang 实现的 Lua 假造机。我们知道 Golang 是静态说话,而 Lua 是动态说话,Golang 的机能和服从各说话中示意得很是不错,但在动态手段上,必定是无法与 Lua 对比。那么假如我们可以或许将二者团结起来,就能综合二者各自的优点了(手动有趣。
在项目 Wiki 中,我们可以知道 gopher-lua 的执行服从和机能仅比 C 实现的 bindings 差。因此从机能方面思量,这应该是一款很是不错的假造机方案。
Hello World
这里给出了一个简朴的 Hello World 措施。我们先是新建了一个假造机,随后对其举办了 DoString(...) 表明执行 lua 代码的操纵,最后将假造机封锁。执行措施,我们将在呼吁行看到 "Hello World" 的字符串。
- package main
- import (
- "github.com/yuin/gopher-lua"
- )
- func main() {
- l := lua.NewState()
- defer l.Close()
- if err := l.DoString(`print("Hello World")`); err != nil {
- panic(err)
- }
- }
- // Hello World
提前编译
在查察上述 DoString(...) 要领的挪用链后,我们发明每执行一次 DoString(...) 或 DoFile(...) ,城市各执行一次 parse 和 compile 。
- func (ls *LState) DoString(source string) error {
- if fn, err := ls.LoadString(source); err != nil {
- return err
- } else {
- ls.Push(fn)
- return ls.PCall(0, MultRet, nil)
- }
- }
- func (ls *LState) LoadString(source string) (*LFunction, error) {
- return ls.Load(strings.NewReader(source), "<string>")
- }
- func (ls *LState) Load(reader io.Reader, name string) (*LFunction, error) {
- chunk, err := parse.Parse(reader, name)
- // ...
- proto, err := Compile(chunk, name)
- // ...
- }
从这一点思量,在同份 Lua 代码将被执行多次(如在 http server 中,每次哀求将执行沟通 Lua 代码)的场景下,假如我们可以或许对代码举办提前编译,那么应该可以或许镌汰 parse 和 compile 的开销(假如这属于 hotpath 代码)。按照 Benchmark 功效,提前编译确实可以或许镌汰不须要的开销。
- package glua_test
- import (
- "bufio"
- "os"
- "strings"
- lua "github.com/yuin/gopher-lua"
- "github.com/yuin/gopher-lua/parse"
- )
- // 编译 lua 代码字段
- func CompileString(source string) (*lua.FunctionProto, error) {
- reader := strings.NewReader(source)
- chunk, err := parse.Parse(reader, source)
- if err != nil {
- return nil, err
- }
- proto, err := lua.Compile(chunk, source)
- if err != nil {
- return nil, err
- }
- return proto, nil
- }
- // 编译 lua 代码文件
- func CompileFile(filePath string) (*lua.FunctionProto, error) {
- file, err := os.Open(filePath)
- defer file.Close()
- if err != nil {
- return nil, err
- }
- reader := bufio.NewReader(file)
- chunk, err := parse.Parse(reader, filePath)
- if err != nil {
- return nil, err
- }
- proto, err := lua.Compile(chunk, filePath)
- if err != nil {
- return nil, err
- }
- return proto, nil
- }
- func BenchmarkRunWithoutPreCompiling(b *testing.B) {
- l := lua.NewState()
- for i := 0; i < b.N; i++ {
- _ = l.DoString(`a = 1 + 1`)
- }
- l.Close()
- }
- func BenchmarkRunWithPreCompiling(b *testing.B) {
- l := lua.NewState()
- proto, _ := CompileString(`a = 1 + 1`)
- lfunc := l.NewFunctionFromProto(proto)
- for i := 0; i < b.N; i++ {
- l.Push(lfunc)
- _ = l.PCall(0, lua.MultRet, nil)
- }
- l.Close()
- }
- // goos: darwin
- // goarch: amd64
- // pkg: glua
- // BenchmarkRunWithoutPreCompiling-8 100000 19392 ns/op 85626 B/op 67 allocs/op
- // BenchmarkRunWithPreCompiling-8 1000000 1162 ns/op 2752 B/op 8 allocs/op
- // PASS
- // ok glua 3.328s
假造机实例池
在同份 Lua 代码被执行的场景下,除了可行使提前编译优化机能外,我们还可以引入假造机实例池。
(编辑:河北网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|