431 lines
9.7 KiB
Go
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
|
||
|
}
|
||
|
}
|