238 lines
4.8 KiB
Go
238 lines
4.8 KiB
Go
package luajit
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
var benchCases = []struct {
|
|
name string
|
|
code string
|
|
}{
|
|
{
|
|
name: "SimpleAddition",
|
|
code: `return 1 + 1`,
|
|
},
|
|
{
|
|
name: "LoopSum",
|
|
code: `
|
|
local sum = 0
|
|
for i = 1, 1000 do
|
|
sum = sum + i
|
|
end
|
|
return sum
|
|
`,
|
|
},
|
|
{
|
|
name: "FunctionCall",
|
|
code: `
|
|
local result = 0
|
|
for i = 1, 100 do
|
|
result = result + i
|
|
end
|
|
return result
|
|
`,
|
|
},
|
|
{
|
|
name: "TableCreation",
|
|
code: `
|
|
local t = {}
|
|
for i = 1, 100 do
|
|
t[i] = i * 2
|
|
end
|
|
return t[50]
|
|
`,
|
|
},
|
|
{
|
|
name: "StringOperations",
|
|
code: `
|
|
local s = "hello"
|
|
for i = 1, 10 do
|
|
s = s .. " world"
|
|
end
|
|
return #s
|
|
`,
|
|
},
|
|
}
|
|
|
|
func BenchmarkLuaDirectExecution(b *testing.B) {
|
|
for _, bc := range benchCases {
|
|
b.Run(bc.name, func(b *testing.B) {
|
|
L := New()
|
|
if L == nil {
|
|
b.Fatal("Failed to create Lua state")
|
|
}
|
|
defer L.Close()
|
|
|
|
// First verify we can execute the code
|
|
if err := L.DoString(bc.code); err != nil {
|
|
b.Fatalf("Failed to execute test code: %v", err)
|
|
}
|
|
L.Pop(1) // Clean up the result
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
// Execute string and get result
|
|
nresults, err := L.ExecuteString(bc.code)
|
|
if err != nil {
|
|
b.Fatalf("Failed to execute code: %v", err)
|
|
}
|
|
L.Pop(nresults) // Clean up any results
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func BenchmarkLuaBytecodeExecution(b *testing.B) {
|
|
// First compile all bytecode
|
|
bytecodes := make(map[string][]byte)
|
|
for _, bc := range benchCases {
|
|
L := New()
|
|
if L == nil {
|
|
b.Fatal("Failed to create Lua state")
|
|
}
|
|
bytecode, err := L.CompileBytecode(bc.code, bc.name)
|
|
if err != nil {
|
|
L.Close()
|
|
b.Fatalf("Error compiling bytecode for %s: %v", bc.name, err)
|
|
}
|
|
bytecodes[bc.name] = bytecode
|
|
L.Close()
|
|
}
|
|
|
|
for _, bc := range benchCases {
|
|
b.Run(bc.name, func(b *testing.B) {
|
|
L := New()
|
|
if L == nil {
|
|
b.Fatal("Failed to create Lua state")
|
|
}
|
|
defer L.Close()
|
|
|
|
bytecode := bytecodes[bc.name]
|
|
|
|
// First verify we can execute the bytecode
|
|
if err := L.LoadBytecode(bytecode, bc.name); err != nil {
|
|
b.Fatalf("Failed to execute test bytecode: %v", err)
|
|
}
|
|
|
|
b.ResetTimer()
|
|
b.SetBytes(int64(len(bytecode))) // Track bytecode size in benchmarks
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
if err := L.LoadBytecode(bytecode, bc.name); err != nil {
|
|
b.Fatalf("Error executing bytecode: %v", err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func BenchmarkTableOperations(b *testing.B) {
|
|
testData := map[string]interface{}{
|
|
"number": 42.0,
|
|
"string": "hello",
|
|
"bool": true,
|
|
"nested": map[string]interface{}{
|
|
"value": 123.0,
|
|
"array": []float64{1.1, 2.2, 3.3},
|
|
},
|
|
}
|
|
|
|
b.Run("PushTable", func(b *testing.B) {
|
|
L := New()
|
|
if L == nil {
|
|
b.Fatal("Failed to create Lua state")
|
|
}
|
|
defer L.Close()
|
|
|
|
// First verify we can push the table
|
|
if err := L.PushTable(testData); err != nil {
|
|
b.Fatalf("Failed to push initial table: %v", err)
|
|
}
|
|
L.Pop(1)
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
if err := L.PushTable(testData); err != nil {
|
|
b.Fatalf("Failed to push table: %v", err)
|
|
}
|
|
L.Pop(1)
|
|
}
|
|
})
|
|
|
|
b.Run("ToTable", func(b *testing.B) {
|
|
L := New()
|
|
if L == nil {
|
|
b.Fatal("Failed to create Lua state")
|
|
}
|
|
defer L.Close()
|
|
|
|
// Keep a table on the stack for repeated conversions
|
|
if err := L.PushTable(testData); err != nil {
|
|
b.Fatalf("Failed to push initial table: %v", err)
|
|
}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
if _, err := L.ToTable(-1); err != nil {
|
|
b.Fatalf("Failed to convert table: %v", err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkValueConversion(b *testing.B) {
|
|
testValues := []struct {
|
|
name string
|
|
value interface{}
|
|
}{
|
|
{"Number", 42.0},
|
|
{"String", "hello world"},
|
|
{"Boolean", true},
|
|
{"Nil", nil},
|
|
}
|
|
|
|
for _, tv := range testValues {
|
|
b.Run("Push"+tv.name, func(b *testing.B) {
|
|
L := New()
|
|
if L == nil {
|
|
b.Fatal("Failed to create Lua state")
|
|
}
|
|
defer L.Close()
|
|
|
|
// First verify we can push the value
|
|
if err := L.PushValue(tv.value); err != nil {
|
|
b.Fatalf("Failed to push initial value: %v", err)
|
|
}
|
|
L.Pop(1)
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
if err := L.PushValue(tv.value); err != nil {
|
|
b.Fatalf("Failed to push value: %v", err)
|
|
}
|
|
L.Pop(1)
|
|
}
|
|
})
|
|
|
|
b.Run("To"+tv.name, func(b *testing.B) {
|
|
L := New()
|
|
if L == nil {
|
|
b.Fatal("Failed to create Lua state")
|
|
}
|
|
defer L.Close()
|
|
|
|
// Keep a value on the stack for repeated conversions
|
|
if err := L.PushValue(tv.value); err != nil {
|
|
b.Fatalf("Failed to push initial value: %v", err)
|
|
}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
if _, err := L.ToValue(-1); err != nil {
|
|
b.Fatalf("Failed to convert value: %v", err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|