-
Notifications
You must be signed in to change notification settings - Fork 689
Description
Thanks for the great project!
Please answer the following before submitting your issue:
- What version of GopherLua are you using? : v0.0.0-20200603152657-dc2b0ca8b37e
- What version of Go are you using? : go version go1.16.5
- What operating system and processor architecture are you using? : linux/amd64
I have a question to validate, if my assumption and tests are correct and are fine to use.
To summarize I am maintainer of https://github.com/zalando/skipper proxy and we have a lua() filter that uses this project to implement it. A filter is an instance that is part of a route. It's not shared between routes. A user just needs to define code like this to execute lua code in request and response path:
function request(ctx, params)
print(c.request.url);
end
function response(ctx, params)
print(c.response.status_code);
endRight now we use for every filter instance a separate lua statepool, but if you think about having 40000 routes and maybe 4000 routes with lua() filters we would have a huge amount of wasted memory or we would have to create LStates all the time.
Right now I am testing it more in depth and tried to share the LState pool. Basically I create at startup 10000 LState and put these into a buffered channel of size 10000. The function to create the LState:
func newState() (*lua.LState, error) {
L := lua.NewState()
L.PreloadModule("base64", base64.Loader)
L.PreloadModule("http", gluahttp.NewHttpModule(&http.Client{}).Loader)
L.PreloadModule("url", gluaurl.Loader)
L.PreloadModule("json", gjson.Loader)
L.SetGlobal("print", L.NewFunction(printToLog))
L.SetGlobal("sleep", L.NewFunction(sleep))
return L, nil
}When the filter is called, we get a LState from the pool and pass it and the compiled lua code from the filter to execute:
func createScript(L *lua.LState, proto *lua.FunctionProto) (*lua.LState, error) {
L.Push(L.NewFunctionFromProto(proto))
err := L.PCall(0, lua.MultRet, nil)
if err != nil {
L.Close()
return nil, err
}
return L, nil
}As far as I see it's not a documented behavior that we can reuse LState and overwrite the Request and Response functions with L.Push(), but it seems to work (tested locally with vegeta and some 10000s of requests).
Is it a safe assumption that overwriting a Function is fine?
Maybe there is a better or safer way to do this.
Do we leak resources that we need to cleanup?
Thanks, sandor