786 lines
18 KiB
Go
786 lines
18 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()
|
|
|
|
TrackMemoryUsage(b, "dostring", func() {
|
|
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()
|
|
|
|
TrackMemoryUsage(b, "compile-run", func() {
|
|
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()
|
|
|
|
TrackMemoryUsage(b, "compile-load-run", func() {
|
|
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()
|
|
|
|
TrackMemoryUsage(b, "precompiled", func() {
|
|
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()
|
|
|
|
TrackMemoryUsage(b, "func-dostring", func() {
|
|
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()
|
|
|
|
TrackMemoryUsage(b, "func-precompiled", func() {
|
|
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()
|
|
|
|
TrackMemoryUsage(b, "loop-dostring", func() {
|
|
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()
|
|
|
|
TrackMemoryUsage(b, "loop-precompiled", func() {
|
|
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()
|
|
|
|
TrackMemoryUsage(b, "table-dostring", func() {
|
|
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()
|
|
|
|
TrackMemoryUsage(b, "table-precompiled", func() {
|
|
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()
|
|
|
|
TrackMemoryUsage(b, "go-func-call", func() {
|
|
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()
|
|
|
|
TrackMemoryUsage(b, "complex-script", func() {
|
|
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()
|
|
|
|
TrackMemoryUsage(b, "complex-precompiled", func() {
|
|
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 {
|
|
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()
|
|
|
|
TrackMemoryUsage(b, "multiple-executions", func() {
|
|
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 {
|
|
b.Fatalf("RunBytecodeWithResults failed: %v", err)
|
|
}
|
|
state.Pop(1) // Pop the result
|
|
}
|
|
})
|
|
}
|
|
|
|
// BenchmarkBatchVsIndividualTableFields compares batch vs individual table field setting
|
|
func BenchmarkBatchVsIndividualTableFields(b *testing.B) {
|
|
b.Run("Individual", func(b *testing.B) {
|
|
state := luajit.New()
|
|
defer state.Close()
|
|
|
|
fields := map[string]string{
|
|
"name": "test",
|
|
"version": "1.0",
|
|
"description": "benchmark",
|
|
"author": "user",
|
|
"license": "MIT",
|
|
"homepage": "example.com",
|
|
"repository": "git://example.com",
|
|
"keywords": "test,bench",
|
|
}
|
|
|
|
TrackMemoryUsage(b, "individual-fields", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
tb := state.NewTableBuilder()
|
|
for k, v := range fields {
|
|
tb.SetString(k, v)
|
|
}
|
|
tb.Build()
|
|
state.Pop(1)
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Batch", func(b *testing.B) {
|
|
state := luajit.New()
|
|
defer state.Close()
|
|
|
|
fields := map[string]string{
|
|
"name": "test",
|
|
"version": "1.0",
|
|
"description": "benchmark",
|
|
"author": "user",
|
|
"license": "MIT",
|
|
"homepage": "example.com",
|
|
"repository": "git://example.com",
|
|
"keywords": "test,bench",
|
|
}
|
|
|
|
TrackMemoryUsage(b, "batch-fields", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
btb := state.NewBatchTableBuilder()
|
|
for k, v := range fields {
|
|
btb.SetString(k, v)
|
|
}
|
|
btb.Build()
|
|
state.Pop(1)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// BenchmarkBatchVsIndividualArrays compares batch vs individual array creation
|
|
func BenchmarkBatchVsIndividualArrays(b *testing.B) {
|
|
intArray := make([]int, 100)
|
|
for i := range intArray {
|
|
intArray[i] = i * 2
|
|
}
|
|
|
|
b.Run("Individual", func(b *testing.B) {
|
|
state := luajit.New()
|
|
defer state.Close()
|
|
|
|
TrackMemoryUsage(b, "individual-array", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
state.CreateTable(len(intArray), 0)
|
|
for j, v := range intArray {
|
|
state.PushNumber(float64(j + 1))
|
|
state.PushNumber(float64(v))
|
|
state.SetTable(-3)
|
|
}
|
|
state.Pop(1)
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Batch", func(b *testing.B) {
|
|
state := luajit.New()
|
|
defer state.Close()
|
|
|
|
TrackMemoryUsage(b, "batch-array", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
state.BatchPushIntArray(intArray)
|
|
state.Pop(1)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// BenchmarkBatchVsIndividualGlobals compares batch vs individual global variable setting
|
|
func BenchmarkBatchVsIndividualGlobals(b *testing.B) {
|
|
globals := map[string]string{
|
|
"APP_NAME": "myapp",
|
|
"APP_VERSION": "1.0.0",
|
|
"APP_ENVIRONMENT": "production",
|
|
"APP_DEBUG": "false",
|
|
"APP_URL": "https://example.com",
|
|
"APP_TIMEZONE": "UTC",
|
|
"DB_HOST": "localhost",
|
|
"DB_PORT": "5432",
|
|
}
|
|
|
|
b.Run("Individual", func(b *testing.B) {
|
|
state := luajit.New()
|
|
defer state.Close()
|
|
|
|
TrackMemoryUsage(b, "individual-globals", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
for k, v := range globals {
|
|
state.PushString(v)
|
|
state.SetGlobal(k)
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Batch", func(b *testing.B) {
|
|
state := luajit.New()
|
|
defer state.Close()
|
|
|
|
TrackMemoryUsage(b, "batch-globals", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
state.BatchSetGlobals(globals)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// BenchmarkBatchVsIndividualTableReads compares batch vs individual table field reading
|
|
func BenchmarkBatchVsIndividualTableReads(b *testing.B) {
|
|
state := luajit.New()
|
|
defer state.Close()
|
|
|
|
// Setup test table
|
|
setupCode := `
|
|
config = {
|
|
database = {host = "localhost", port = 5432, name = "mydb"},
|
|
server = {host = "0.0.0.0", port = 8080, ssl = true},
|
|
logging = {level = "info", file = "/var/log/app.log"},
|
|
cache = {enabled = true, ttl = 300, size = 1000}
|
|
}
|
|
`
|
|
if err := state.DoString(setupCode); err != nil {
|
|
b.Fatalf("Setup failed: %v", err)
|
|
}
|
|
|
|
keys := []string{"database", "server", "logging", "cache"}
|
|
|
|
b.Run("Individual", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "individual-reads", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
state.GetGlobal("config")
|
|
values := make(map[string]any)
|
|
for _, key := range keys {
|
|
state.GetField(-1, key)
|
|
if val, err := state.ToValue(-1); err == nil {
|
|
values[key] = val
|
|
}
|
|
state.Pop(1)
|
|
}
|
|
state.Pop(1)
|
|
_ = values
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Batch", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "batch-reads", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
state.GetGlobal("config")
|
|
reader := state.NewBatchTableReader(-1)
|
|
values, _ := reader.ReadFields(keys)
|
|
state.Pop(1)
|
|
_ = values
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// BenchmarkBatchValuePusher compares batch vs individual value pushing
|
|
func BenchmarkBatchValuePusher(b *testing.B) {
|
|
values := []any{"hello", 42, true, 3.14, "world", 100, false, 2.718}
|
|
|
|
b.Run("Individual", func(b *testing.B) {
|
|
state := luajit.New()
|
|
defer state.Close()
|
|
|
|
TrackMemoryUsage(b, "individual-push", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
for _, v := range values {
|
|
state.PushValue(v)
|
|
}
|
|
state.Pop(len(values))
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Batch", func(b *testing.B) {
|
|
state := luajit.New()
|
|
defer state.Close()
|
|
|
|
TrackMemoryUsage(b, "batch-push", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
pusher := state.NewBatchValuePusher()
|
|
for _, v := range values {
|
|
pusher.Add(v)
|
|
}
|
|
pusher.Push()
|
|
state.Pop(len(values))
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// BenchmarkBatchTypeChecking compares batch vs individual type checking
|
|
func BenchmarkBatchTypeChecking(b *testing.B) {
|
|
state := luajit.New()
|
|
defer state.Close()
|
|
|
|
// Setup test values on stack
|
|
state.PushString("hello")
|
|
state.PushNumber(42)
|
|
state.PushBoolean(true)
|
|
state.PushNil()
|
|
|
|
checks := []luajit.TypeCheck{
|
|
{Index: 1, ExpectedType: luajit.TypeString},
|
|
{Index: 2, ExpectedType: luajit.TypeNumber},
|
|
{Index: 3, ExpectedType: luajit.TypeBoolean},
|
|
{Index: 4, ExpectedType: luajit.TypeNil},
|
|
}
|
|
|
|
b.Run("Individual", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "individual-check", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
for _, check := range checks {
|
|
if state.GetType(check.Index) != check.ExpectedType {
|
|
b.Fatal("Type mismatch")
|
|
}
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Batch", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "batch-check", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
if err := state.BatchCheckTypes(checks); err != nil {
|
|
b.Fatal("Type check failed:", err)
|
|
}
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// BenchmarkBatchGlobalManager benchmarks the batch global manager
|
|
func BenchmarkBatchGlobalManager(b *testing.B) {
|
|
state := luajit.New()
|
|
defer state.Close()
|
|
|
|
setGlobals := map[string]string{
|
|
"VAR1": "value1",
|
|
"VAR2": "value2",
|
|
"VAR3": "value3",
|
|
"VAR4": "value4",
|
|
}
|
|
|
|
getGlobals := []string{"VAR1", "VAR2", "VAR3", "VAR4"}
|
|
|
|
b.Run("Individual", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "individual-global-mgmt", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
// Set globals
|
|
for k, v := range setGlobals {
|
|
state.PushString(v)
|
|
state.SetGlobal(k)
|
|
}
|
|
// Get globals
|
|
results := make(map[string]any)
|
|
for _, name := range getGlobals {
|
|
state.GetGlobal(name)
|
|
if val, err := state.ToValue(-1); err == nil {
|
|
results[name] = val
|
|
}
|
|
state.Pop(1)
|
|
}
|
|
_ = results
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Batch", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "batch-global-mgmt", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
mgr := state.NewBatchGlobalManager()
|
|
for k, v := range setGlobals {
|
|
mgr.QueueSet(k, v)
|
|
}
|
|
for _, name := range getGlobals {
|
|
mgr.QueueGet(name)
|
|
}
|
|
results, _ := mgr.Execute()
|
|
_ = results
|
|
}
|
|
})
|
|
})
|
|
}
|