Skip to content

Instantly share code, notes, and snippets.

@sakateka
Last active November 24, 2016 20:38
Show Gist options
  • Save sakateka/731dfc23a08091397eded120d0417472 to your computer and use it in GitHub Desktop.
Save sakateka/731dfc23a08091397eded120d0417472 to your computer and use it in GitHub Desktop.
lua plugin benchmark
package main
import (
"fmt"
"reflect"
"strconv"
luar "github.com/layeh/gopher-luar"
lua "github.com/yuin/gopher-lua"
)
type DataItem map[string]interface{}
type DataType map[string]DataItem
func ToLuaTable(l *lua.LState, in DataType) (*lua.LTable, error) {
out := l.NewTable()
rv := reflect.ValueOf(in)
if err := dumpMap(l, out, "", rv); err != nil {
return nil, err
}
return out, nil
}
func dumpMap(l *lua.LState, t *lua.LTable, k string, rv reflect.Value) (err error) {
var innerTable *lua.LTable
if k != "" {
innerTable = l.NewTable()
t.RawSetString(k, innerTable)
} else {
innerTable = t
}
keys := rv.MapKeys()
for _, key := range keys {
itemInterface := reflect.ValueOf(rv.MapIndex(key).Interface())
//logger.Infof("Item of key %s is: %v", key, itemInterface.Kind())
switch itemInterface.Kind() {
case reflect.Slice, reflect.Array:
err = dumpSlice(l, innerTable, key.String(), itemInterface)
case reflect.Map:
err = dumpMap(l, innerTable, key.String(), itemInterface)
default:
v, err := dumpPoint(itemInterface)
if err != nil {
return err
}
innerTable.RawSetString(key.String(), v)
}
if err != nil {
return
}
}
return nil
}
func dumpSlice(l *lua.LState, t *lua.LTable, k string, rv reflect.Value) error {
/*
if len(s.Fields) == 0 || len(s.Fields) != rv.Len() {
msg := fmt.Sprintf("%s Unable to send a slice. Fields len %d, len of value %d",
s.id, len(s.Fields), rv.Len())
logger.Errf("%s", msg)
return fmt.Errorf(msg)
}
*/
innerTable := l.NewTable()
t.RawSetString(k, innerTable)
for i := 0; i < rv.Len(); i++ {
item := reflect.ValueOf(rv.Index(i).Interface())
v, err := dumpPoint(item)
if err != nil {
return err
}
innerTable.Insert(i+1, v)
}
return nil
}
func dumpPoint(value reflect.Value) (ret lua.LNumber, err error) {
switch value.Kind() {
case reflect.Float32, reflect.Float64:
ret = lua.LNumber(value.Float())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
ret = lua.LNumber(float64(value.Int()))
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
reflect.Uint64, reflect.Uintptr:
ret = lua.LNumber(float64(value.Uint()))
case reflect.String:
num, err := strconv.ParseFloat(value.String(), 64)
if err == nil {
ret = lua.LNumber(num)
}
default:
err = fmt.Errorf("value %s is Not a Number: %v", value.Kind(), value)
}
return
}
var data = DataType{
"host1": map[string]interface{}{
"1error": []float64{11133.4, 111222.2, 1113434.3},
"1rps": 111234,
"1timings": 1110.000,
},
"host2": map[string]interface{}{
"2error": []float64{22233.4, 222222.2, 2223434.3},
"2rps": 222234,
"2timings": 2220.000,
},
"host3": map[string]interface{}{
"3error": []float64{22233.4, 222222.2, 2223434.3},
"3rps": 222234,
"3timings": 2220.000,
},
"host4": map[string]interface{}{
"4error": []float64{22233.4, 222222.2, 2223434.3},
"4rps": 222234,
"4timings": 2220.000,
},
"host5": map[string]interface{}{
"5error": []float64{22233.4, 222222.2, 2223434.3},
"5rps": 222234,
"5timings": 2220.000,
},
"host6": map[string]interface{}{
"6error": []float64{22233.4, 222222.2, 2223434.3},
"6rps": 222234,
"6timings": 2220.000,
},
"host7": map[string]interface{}{
"7error": []float64{22233.4, 222222.2, 2223434.3},
"7rps": 222234,
"7timings": 2220.000,
},
}
func main() {
l := lua.NewState()
defer l.Close()
if err := l.DoFile("plugin.lua"); err != nil {
panic(err)
}
l.SetGlobal("dt", luar.New(l, data))
l.Push(l.GetGlobal("printdt"))
l.Call(0, 0)
/*
table, err := ToLuaTable(l, data)
if err != nil {
log.Fatalln(err)
}
l.SetGlobal("table", table)
l.Push(l.GetGlobal("printtable"))
l.Call(0, 0)
*/
}
package main
import (
"log"
"testing"
luar "github.com/layeh/gopher-luar"
lua "github.com/yuin/gopher-lua"
)
func BenchmarkTableTraverse(b *testing.B) {
for i := 0; i < b.N; i++ {
l := lua.NewState()
defer l.Close()
if err := l.DoFile("plugin.lua"); err != nil {
panic(err)
}
l.SetGlobal("dt", luar.New(l, data))
l.Push(l.GetGlobal("printdt"))
l.Call(0, 0)
}
}
func BenchmarkToLuaTable(b *testing.B) {
for i := 0; i < b.N; i++ {
l := lua.NewState()
defer l.Close()
if err := l.DoFile("plugin.lua"); err != nil {
panic(err)
}
table, err := ToLuaTable(l, data)
if err != nil {
log.Fatalln(err)
}
l.SetGlobal("table", table)
l.Push(l.GetGlobal("printtable"))
l.Call(0, 0)
}
}
function printdt()
traverse(dt, "", 0)
end
function traverse(item, key, step)
ok, data = pcall(function() return item() end)
if ok then
for k, v in data do
step = step + 1
if key ~= "" then
k = key.."."..k
end
traverse(v, k, step)
end
else
print(key.. "on step" .. step.. " :".. string.format("%.3f", item))
end
end
function printtable()
pprint("", table)
end
function pprint(key, t)
for k, v in pairs(t) do
if key ~= "" then
k = key .. "." .. k
end
if type(v) == "table" then
pprint(k, v)
else
print(k .. " is " .. string.format("%.3f", v))
end
end
end
BenchmarkTableTraverse-4
1000 1183431 ns/op
BenchmarkToLuaTable-4
2000 663869 ns/op
PASS
ok tmp 2.745s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment