LuaJIT-to-Go/bench/bench_test.go
2025-02-26 07:00:01 -06:00

431 lines
9.7 KiB
Go

package luajit_bench
import (
"testing"
luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
)
// BenchmarkSimpleDoString benchmarks direct execution of a simple expression
func BenchmarkSimpleDoString(b *testing.B) {
state := luajit.New()
if state == nil {
b.Fatal("Failed to create Lua state")
}
defer state.Close()
code := "local x = 1 + 1"
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := state.DoString(code); err != nil {
b.Fatalf("DoString failed: %v", err)
}
}
}
// BenchmarkSimpleCompileAndRun benchmarks compile and run of a simple expression
func BenchmarkSimpleCompileAndRun(b *testing.B) {
state := luajit.New()
if state == nil {
b.Fatal("Failed to create Lua state")
}
defer state.Close()
code := "local x = 1 + 1"
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := state.CompileAndRun(code, "simple"); err != nil {
b.Fatalf("CompileAndRun failed: %v", err)
}
}
}
// BenchmarkSimpleCompileLoadRun benchmarks compile, load, and run of a simple expression
func BenchmarkSimpleCompileLoadRun(b *testing.B) {
state := luajit.New()
if state == nil {
b.Fatal("Failed to create Lua state")
}
defer state.Close()
code := "local x = 1 + 1"
b.ResetTimer()
for i := 0; i < b.N; i++ {
bytecode, err := state.CompileBytecode(code, "simple")
if err != nil {
b.Fatalf("CompileBytecode failed: %v", err)
}
if err := state.LoadAndRunBytecode(bytecode, "simple"); err != nil {
b.Fatalf("LoadAndRunBytecode failed: %v", err)
}
}
}
// BenchmarkSimplePrecompiledBytecode benchmarks running precompiled bytecode
func BenchmarkSimplePrecompiledBytecode(b *testing.B) {
state := luajit.New()
if state == nil {
b.Fatal("Failed to create Lua state")
}
defer state.Close()
code := "local x = 1 + 1"
bytecode, err := state.CompileBytecode(code, "simple")
if err != nil {
b.Fatalf("CompileBytecode failed: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := state.LoadAndRunBytecode(bytecode, "simple"); err != nil {
b.Fatalf("LoadAndRunBytecode failed: %v", err)
}
}
}
// BenchmarkFunctionCallDoString benchmarks direct execution of a function call
func BenchmarkFunctionCallDoString(b *testing.B) {
state := luajit.New()
if state == nil {
b.Fatal("Failed to create Lua state")
}
defer state.Close()
// Setup function
setupCode := `
function add(a, b)
return a + b
end
`
if err := state.DoString(setupCode); err != nil {
b.Fatalf("Failed to set up function: %v", err)
}
code := "local result = add(10, 20)"
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := state.DoString(code); err != nil {
b.Fatalf("DoString failed: %v", err)
}
}
}
// BenchmarkFunctionCallPrecompiled benchmarks precompiled function call
func BenchmarkFunctionCallPrecompiled(b *testing.B) {
state := luajit.New()
if state == nil {
b.Fatal("Failed to create Lua state")
}
defer state.Close()
// Setup function
setupCode := `
function add(a, b)
return a + b
end
`
if err := state.DoString(setupCode); err != nil {
b.Fatalf("Failed to set up function: %v", err)
}
code := "local result = add(10, 20)"
bytecode, err := state.CompileBytecode(code, "call")
if err != nil {
b.Fatalf("CompileBytecode failed: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := state.LoadAndRunBytecode(bytecode, "call"); err != nil {
b.Fatalf("LoadAndRunBytecode failed: %v", err)
}
}
}
// BenchmarkLoopDoString benchmarks direct execution of a loop
func BenchmarkLoopDoString(b *testing.B) {
state := luajit.New()
if state == nil {
b.Fatal("Failed to create Lua state")
}
defer state.Close()
code := `
local sum = 0
for i = 1, 1000 do
sum = sum + i
end
`
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := state.DoString(code); err != nil {
b.Fatalf("DoString failed: %v", err)
}
}
}
// BenchmarkLoopPrecompiled benchmarks precompiled loop execution
func BenchmarkLoopPrecompiled(b *testing.B) {
state := luajit.New()
if state == nil {
b.Fatal("Failed to create Lua state")
}
defer state.Close()
code := `
local sum = 0
for i = 1, 1000 do
sum = sum + i
end
`
bytecode, err := state.CompileBytecode(code, "loop")
if err != nil {
b.Fatalf("CompileBytecode failed: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := state.LoadAndRunBytecode(bytecode, "loop"); err != nil {
b.Fatalf("LoadAndRunBytecode failed: %v", err)
}
}
}
// BenchmarkTableOperationsDoString benchmarks direct execution of table operations
func BenchmarkTableOperationsDoString(b *testing.B) {
state := luajit.New()
if state == nil {
b.Fatal("Failed to create Lua state")
}
defer state.Close()
code := `
local t = {}
for i = 1, 100 do
t[i] = i * 2
end
local sum = 0
for i, v in ipairs(t) do
sum = sum + v
end
`
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := state.DoString(code); err != nil {
b.Fatalf("DoString failed: %v", err)
}
}
}
// BenchmarkTableOperationsPrecompiled benchmarks precompiled table operations
func BenchmarkTableOperationsPrecompiled(b *testing.B) {
state := luajit.New()
if state == nil {
b.Fatal("Failed to create Lua state")
}
defer state.Close()
code := `
local t = {}
for i = 1, 100 do
t[i] = i * 2
end
local sum = 0
for i, v in ipairs(t) do
sum = sum + v
end
`
bytecode, err := state.CompileBytecode(code, "table")
if err != nil {
b.Fatalf("CompileBytecode failed: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := state.LoadAndRunBytecode(bytecode, "table"); err != nil {
b.Fatalf("LoadAndRunBytecode failed: %v", err)
}
}
}
// BenchmarkGoFunctionCall benchmarks calling a Go function from Lua
func BenchmarkGoFunctionCall(b *testing.B) {
state := luajit.New()
if state == nil {
b.Fatal("Failed to create Lua state")
}
defer state.Close()
// Register a simple Go function
add := func(s *luajit.State) int {
a := s.ToNumber(1)
b := s.ToNumber(2)
s.PushNumber(a + b)
return 1
}
if err := state.RegisterGoFunction("add", add); err != nil {
b.Fatalf("RegisterGoFunction failed: %v", err)
}
code := "local result = add(10, 20)"
bytecode, err := state.CompileBytecode(code, "gofunc")
if err != nil {
b.Fatalf("CompileBytecode failed: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := state.LoadAndRunBytecode(bytecode, "gofunc"); err != nil {
b.Fatalf("LoadAndRunBytecode failed: %v", err)
}
}
}
// BenchmarkComplexScript benchmarks a more complex script
func BenchmarkComplexScript(b *testing.B) {
state := luajit.New()
if state == nil {
b.Fatal("Failed to create Lua state")
}
defer state.Close()
code := `
-- Define a simple class
local Class = {}
Class.__index = Class
function Class.new(x, y)
local self = setmetatable({}, Class)
self.x = x or 0
self.y = y or 0
return self
end
function Class:move(dx, dy)
self.x = self.x + dx
self.y = self.y + dy
return self
end
function Class:getPosition()
return self.x, self.y
end
-- Create instances and operate on them
local instances = {}
for i = 1, 50 do
instances[i] = Class.new(i, i*2)
end
local result = 0
for i, obj in ipairs(instances) do
obj:move(i, -i)
local x, y = obj:getPosition()
result = result + x + y
end
return result
`
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := state.ExecuteWithResult(code); err != nil {
b.Fatalf("ExecuteWithResult failed: %v", err)
}
}
}
// BenchmarkComplexScriptPrecompiled benchmarks a precompiled complex script
func BenchmarkComplexScriptPrecompiled(b *testing.B) {
state := luajit.New()
if state == nil {
b.Fatal("Failed to create Lua state")
}
defer state.Close()
code := `
-- Define a simple class
local Class = {}
Class.__index = Class
function Class.new(x, y)
local self = setmetatable({}, Class)
self.x = x or 0
self.y = y or 0
return self
end
function Class:move(dx, dy)
self.x = self.x + dx
self.y = self.y + dy
return self
end
function Class:getPosition()
return self.x, self.y
end
-- Create instances and operate on them
local instances = {}
for i = 1, 50 do
instances[i] = Class.new(i, i*2)
end
local result = 0
for i, obj in ipairs(instances) do
obj:move(i, -i)
local x, y = obj:getPosition()
result = result + x + y
end
return result
`
bytecode, err := state.CompileBytecode(code, "complex")
if err != nil {
b.Fatalf("CompileBytecode failed: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := state.LoadBytecode(bytecode, "complex"); err != nil {
b.Fatalf("LoadBytecode failed: %v", err)
}
if err := state.RunBytecodeWithResults(1); err != nil { // Assuming this method exists to get the return value
b.Fatalf("RunBytecodeWithResults failed: %v", err)
}
state.Pop(1) // Pop the result
}
}
// BenchmarkMultipleExecutions benchmarks executing the same bytecode multiple times
func BenchmarkMultipleExecutions(b *testing.B) {
state := luajit.New()
if state == nil {
b.Fatal("Failed to create Lua state")
}
defer state.Close()
// Setup a stateful environment
setupCode := `
counter = 0
function increment(amount)
counter = counter + (amount or 1)
return counter
end
`
if err := state.DoString(setupCode); err != nil {
b.Fatalf("Failed to set up environment: %v", err)
}
// Compile the function call
code := "return increment(5)"
bytecode, err := state.CompileBytecode(code, "increment")
if err != nil {
b.Fatalf("CompileBytecode failed: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := state.LoadBytecode(bytecode, "increment"); err != nil {
b.Fatalf("LoadBytecode failed: %v", err)
}
if err := state.RunBytecodeWithResults(1); err != nil { // Assuming this method exists
b.Fatalf("RunBytecodeWithResults failed: %v", err)
}
state.Pop(1) // Pop the result
}
}