773 lines
16 KiB
Go
773 lines
16 KiB
Go
package luajit_bench
|
|
|
|
import (
|
|
"testing"
|
|
|
|
luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
|
|
)
|
|
|
|
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 := luajit.New()
|
|
if L == nil {
|
|
b.Fatal("Failed to create Lua state")
|
|
}
|
|
defer L.Close()
|
|
defer L.Cleanup()
|
|
|
|
// First verify we can execute the code
|
|
if err := L.DoString(bc.code); err != nil {
|
|
b.Fatalf("Failed to execute test code: %v", err)
|
|
}
|
|
|
|
b.ResetTimer()
|
|
|
|
TrackMemoryUsage(b, "direct-"+bc.name, func() {
|
|
for i := 0; i < b.N; i++ {
|
|
// Execute string and get results
|
|
nresults, err := L.Execute(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 := luajit.New()
|
|
if L == nil {
|
|
b.Fatal("Failed to create Lua state")
|
|
}
|
|
defer L.Cleanup()
|
|
|
|
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 := luajit.New()
|
|
if L == nil {
|
|
b.Fatal("Failed to create Lua state")
|
|
}
|
|
defer L.Close()
|
|
defer L.Cleanup()
|
|
|
|
bytecode := bytecodes[bc.name]
|
|
|
|
// First verify we can execute the bytecode
|
|
if err := L.LoadAndRunBytecodeWithResults(bytecode, bc.name, 1); err != nil {
|
|
b.Fatalf("Failed to execute test bytecode: %v", err)
|
|
}
|
|
L.Pop(1) // Clean up the result
|
|
|
|
b.ResetTimer()
|
|
b.SetBytes(int64(len(bytecode))) // Track bytecode size in benchmarks
|
|
|
|
TrackMemoryUsage(b, "bytecode-"+bc.name, func() {
|
|
for i := 0; i < b.N; i++ {
|
|
if err := L.LoadAndRunBytecode(bytecode, bc.name); err != nil {
|
|
b.Fatalf("Error executing bytecode: %v", err)
|
|
}
|
|
}
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkBatchTableOperations compares batch vs individual table operations
|
|
func BenchmarkBatchTableOperations(b *testing.B) {
|
|
testData := map[string]any{
|
|
"name": "testapp",
|
|
"version": "1.0.0",
|
|
"port": 8080,
|
|
"debug": true,
|
|
"timeout": 30.5,
|
|
"tags": []string{"web", "api", "service"},
|
|
"limits": []int{100, 200, 300, 400, 500},
|
|
}
|
|
|
|
b.Run("Individual", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
defer L.Cleanup()
|
|
|
|
TrackMemoryUsage(b, "table-individual", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
tb := L.NewTableBuilder()
|
|
for k, v := range testData {
|
|
switch val := v.(type) {
|
|
case string:
|
|
tb.SetString(k, val)
|
|
case int:
|
|
tb.SetNumber(k, float64(val))
|
|
case bool:
|
|
tb.SetBool(k, val)
|
|
case float64:
|
|
tb.SetNumber(k, val)
|
|
default:
|
|
tb.SetTable(k, v)
|
|
}
|
|
}
|
|
tb.Build()
|
|
L.Pop(1)
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Batch", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
defer L.Cleanup()
|
|
|
|
TrackMemoryUsage(b, "table-batch", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
tb := L.NewTableBuilder()
|
|
tb.BatchBuild(testData)
|
|
tb.Build()
|
|
L.Pop(1)
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("BatchTableBuilder", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
defer L.Cleanup()
|
|
|
|
TrackMemoryUsage(b, "table-batch-builder", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
btb := L.NewBatchTableBuilder()
|
|
for k, v := range testData {
|
|
switch val := v.(type) {
|
|
case string:
|
|
btb.SetString(k, val)
|
|
case int:
|
|
btb.SetNumber(k, float64(val))
|
|
case bool:
|
|
btb.SetBool(k, val)
|
|
case float64:
|
|
btb.SetNumber(k, val)
|
|
default:
|
|
btb.SetTable(k, v)
|
|
}
|
|
}
|
|
btb.Build()
|
|
L.Pop(1)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// BenchmarkBatchArrayOperations compares different array creation methods
|
|
func BenchmarkBatchArrayOperations(b *testing.B) {
|
|
intArray := make([]int, 50)
|
|
stringArray := make([]string, 50)
|
|
floatArray := make([]float64, 50)
|
|
boolArray := make([]bool, 50)
|
|
|
|
for i := range 50 {
|
|
intArray[i] = i * 2
|
|
stringArray[i] = "item" + string(rune('0'+i%10))
|
|
floatArray[i] = float64(i) * 1.5
|
|
boolArray[i] = i%2 == 0
|
|
}
|
|
|
|
b.Run("IntArray_Individual", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
TrackMemoryUsage(b, "int-array-individual", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.PushValue(intArray)
|
|
L.Pop(1)
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("IntArray_Batch", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
TrackMemoryUsage(b, "int-array-batch", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.BatchPushIntArray(intArray)
|
|
L.Pop(1)
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("StringArray_Individual", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
TrackMemoryUsage(b, "string-array-individual", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.PushValue(stringArray)
|
|
L.Pop(1)
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("StringArray_Batch", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
TrackMemoryUsage(b, "string-array-batch", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.BatchPushStringArray(stringArray)
|
|
L.Pop(1)
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("FloatArray_Individual", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
TrackMemoryUsage(b, "float-array-individual", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.PushValue(floatArray)
|
|
L.Pop(1)
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("FloatArray_Batch", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
TrackMemoryUsage(b, "float-array-batch", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.BatchPushFloatArray(floatArray)
|
|
L.Pop(1)
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("BoolArray_Individual", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
TrackMemoryUsage(b, "bool-array-individual", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.PushValue(boolArray)
|
|
L.Pop(1)
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("BoolArray_Batch", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
TrackMemoryUsage(b, "bool-array-batch", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.BatchPushBoolArray(boolArray)
|
|
L.Pop(1)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// BenchmarkBatchGlobalOperations compares global variable operations
|
|
func BenchmarkBatchGlobalOperations(b *testing.B) {
|
|
globals := map[string]string{
|
|
"APP_NAME": "myapp",
|
|
"APP_VERSION": "1.0.0",
|
|
"APP_ENV": "production",
|
|
"DB_HOST": "localhost",
|
|
"DB_PORT": "5432",
|
|
"DB_NAME": "mydb",
|
|
"CACHE_TTL": "300",
|
|
"LOG_LEVEL": "info",
|
|
}
|
|
|
|
b.Run("Individual_Set", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
TrackMemoryUsage(b, "globals-individual-set", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
for k, v := range globals {
|
|
L.PushString(v)
|
|
L.SetGlobal(k)
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Batch_Set", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
TrackMemoryUsage(b, "globals-batch-set", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.BatchSetGlobals(globals)
|
|
}
|
|
})
|
|
})
|
|
|
|
// Setup globals for read tests
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
L.BatchSetGlobals(globals)
|
|
|
|
globalNames := make([]string, 0, len(globals))
|
|
for k := range globals {
|
|
globalNames = append(globalNames, k)
|
|
}
|
|
|
|
b.Run("Individual_Get", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "globals-individual-get", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
values := make(map[string]any)
|
|
for _, name := range globalNames {
|
|
L.GetGlobal(name)
|
|
if val, err := L.ToValue(-1); err == nil {
|
|
values[name] = val
|
|
}
|
|
L.Pop(1)
|
|
}
|
|
_ = values
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Batch_Get", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "globals-batch-get", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
startTop := L.GetTop()
|
|
L.BatchGetGlobals(globalNames)
|
|
values := make(map[string]any, len(globalNames))
|
|
for j, name := range globalNames {
|
|
if val, err := L.ToValue(startTop + j + 1); err == nil {
|
|
values[name] = val
|
|
}
|
|
}
|
|
L.SetTop(startTop)
|
|
_ = values
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// BenchmarkBatchTableReading compares table field reading methods
|
|
func BenchmarkBatchTableReading(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
// Create a complex nested table structure
|
|
setupCode := `
|
|
config = {
|
|
database = {
|
|
host = "localhost",
|
|
port = 5432,
|
|
name = "myapp",
|
|
timeout = 30,
|
|
ssl = true,
|
|
pool = {min = 5, max = 20}
|
|
},
|
|
server = {
|
|
host = "0.0.0.0",
|
|
port = 8080,
|
|
workers = 4,
|
|
timeout = 60,
|
|
ssl = false,
|
|
middleware = {"cors", "auth", "logging"}
|
|
},
|
|
cache = {
|
|
enabled = true,
|
|
ttl = 300,
|
|
size = 1000,
|
|
backend = "redis",
|
|
cluster = false
|
|
},
|
|
logging = {
|
|
level = "info",
|
|
file = "/var/log/app.log",
|
|
rotate = true,
|
|
max_size = 100,
|
|
format = "json"
|
|
}
|
|
}
|
|
`
|
|
if err := L.DoString(setupCode); err != nil {
|
|
b.Fatalf("Setup failed: %v", err)
|
|
}
|
|
|
|
topLevelKeys := []string{"database", "server", "cache", "logging"}
|
|
dbKeys := []string{"host", "port", "name", "timeout", "ssl"}
|
|
|
|
b.Run("Individual_TopLevel", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "table-read-individual", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.GetGlobal("config")
|
|
values := make(map[string]any)
|
|
for _, key := range topLevelKeys {
|
|
L.GetField(-1, key)
|
|
if val, err := L.ToValue(-1); err == nil {
|
|
values[key] = val
|
|
}
|
|
L.Pop(1)
|
|
}
|
|
L.Pop(1)
|
|
_ = values
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Batch_TopLevel", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "table-read-batch", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.GetGlobal("config")
|
|
reader := L.NewBatchTableReader(-1)
|
|
values, _ := reader.ReadFields(topLevelKeys)
|
|
L.Pop(1)
|
|
_ = values
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Individual_Nested", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "nested-read-individual", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.GetGlobal("config")
|
|
L.GetField(-1, "database")
|
|
values := make(map[string]any)
|
|
for _, key := range dbKeys {
|
|
L.GetField(-1, key)
|
|
if val, err := L.ToValue(-1); err == nil {
|
|
values[key] = val
|
|
}
|
|
L.Pop(1)
|
|
}
|
|
L.Pop(2)
|
|
_ = values
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Batch_Nested", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "nested-read-batch", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.GetGlobal("config")
|
|
L.GetField(-1, "database")
|
|
reader := L.NewBatchTableReader(-1)
|
|
values, _ := reader.ReadFields(dbKeys)
|
|
L.Pop(2)
|
|
_ = values
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// BenchmarkBatchValuePushing compares value pushing methods
|
|
func BenchmarkBatchValuePushing(b *testing.B) {
|
|
mixedValues := []any{
|
|
"string1", 42, true, 3.14,
|
|
"string2", 100, false, 2.718,
|
|
"string3", 256, true, 1.414,
|
|
"string4", 500, false, 0.577,
|
|
}
|
|
|
|
stringValues := []any{"hello", "world", "test", "bench", "mark", "go", "lua", "jit"}
|
|
numberValues := []any{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
|
|
|
b.Run("Mixed_Individual", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
TrackMemoryUsage(b, "mixed-individual", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
for _, v := range mixedValues {
|
|
L.PushValue(v)
|
|
}
|
|
L.Pop(len(mixedValues))
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Mixed_Batch", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
TrackMemoryUsage(b, "mixed-batch", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
pusher := L.NewBatchValuePusher()
|
|
for _, v := range mixedValues {
|
|
pusher.Add(v)
|
|
}
|
|
pusher.Push()
|
|
L.Pop(len(mixedValues))
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Strings_Individual", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
TrackMemoryUsage(b, "strings-individual", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
for _, v := range stringValues {
|
|
L.PushValue(v)
|
|
}
|
|
L.Pop(len(stringValues))
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Strings_Batch", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
TrackMemoryUsage(b, "strings-batch", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
pusher := L.NewBatchValuePusher()
|
|
for _, v := range stringValues {
|
|
pusher.Add(v)
|
|
}
|
|
pusher.Push()
|
|
L.Pop(len(stringValues))
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Numbers_Individual", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
TrackMemoryUsage(b, "numbers-individual", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
for _, v := range numberValues {
|
|
L.PushValue(v)
|
|
}
|
|
L.Pop(len(numberValues))
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("Numbers_Batch", func(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
TrackMemoryUsage(b, "numbers-batch", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
pusher := L.NewBatchValuePusher()
|
|
for _, v := range numberValues {
|
|
pusher.Add(v)
|
|
}
|
|
pusher.Push()
|
|
L.Pop(len(numberValues))
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// BenchmarkBatchExtraction compares array extraction methods
|
|
func BenchmarkBatchExtraction(b *testing.B) {
|
|
L := luajit.New()
|
|
defer L.Close()
|
|
|
|
// Create test arrays in Lua
|
|
setupCode := `
|
|
int_array = {}
|
|
for i = 1, 100 do
|
|
int_array[i] = i * 2
|
|
end
|
|
|
|
float_array = {}
|
|
for i = 1, 100 do
|
|
float_array[i] = i * 1.5
|
|
end
|
|
|
|
string_array = {}
|
|
for i = 1, 100 do
|
|
string_array[i] = "item" .. i
|
|
end
|
|
|
|
bool_array = {}
|
|
for i = 1, 100 do
|
|
bool_array[i] = (i % 2 == 0)
|
|
end
|
|
`
|
|
if err := L.DoString(setupCode); err != nil {
|
|
b.Fatalf("Setup failed: %v", err)
|
|
}
|
|
|
|
b.Run("IntArray_Individual", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "int-extract-individual", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.GetGlobal("int_array")
|
|
result := make([]int, 100)
|
|
for j := 1; j <= 100; j++ {
|
|
L.PushNumber(float64(j))
|
|
L.GetTable(-2)
|
|
result[j-1] = int(L.ToNumber(-1))
|
|
L.Pop(1)
|
|
}
|
|
L.Pop(1)
|
|
_ = result
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("IntArray_Batch", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "int-extract-batch", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.GetGlobal("int_array")
|
|
result, _ := L.BatchExtractIntArray(-1, 100)
|
|
L.Pop(1)
|
|
_ = result
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("FloatArray_Individual", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "float-extract-individual", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.GetGlobal("float_array")
|
|
result := make([]float64, 100)
|
|
for j := 1; j <= 100; j++ {
|
|
L.PushNumber(float64(j))
|
|
L.GetTable(-2)
|
|
result[j-1] = L.ToNumber(-1)
|
|
L.Pop(1)
|
|
}
|
|
L.Pop(1)
|
|
_ = result
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("FloatArray_Batch", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "float-extract-batch", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.GetGlobal("float_array")
|
|
result, _ := L.BatchExtractFloatArray(-1, 100)
|
|
L.Pop(1)
|
|
_ = result
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("StringArray_Individual", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "string-extract-individual", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.GetGlobal("string_array")
|
|
result := make([]string, 100)
|
|
for j := 1; j <= 100; j++ {
|
|
L.PushNumber(float64(j))
|
|
L.GetTable(-2)
|
|
result[j-1] = L.ToString(-1)
|
|
L.Pop(1)
|
|
}
|
|
L.Pop(1)
|
|
_ = result
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("StringArray_Batch", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "string-extract-batch", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.GetGlobal("string_array")
|
|
result, _ := L.BatchExtractStringArray(-1, 100)
|
|
L.Pop(1)
|
|
_ = result
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("BoolArray_Individual", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "bool-extract-individual", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.GetGlobal("bool_array")
|
|
result := make([]bool, 100)
|
|
for j := 1; j <= 100; j++ {
|
|
L.PushNumber(float64(j))
|
|
L.GetTable(-2)
|
|
result[j-1] = L.ToBoolean(-1)
|
|
L.Pop(1)
|
|
}
|
|
L.Pop(1)
|
|
_ = result
|
|
}
|
|
})
|
|
})
|
|
|
|
b.Run("BoolArray_Batch", func(b *testing.B) {
|
|
TrackMemoryUsage(b, "bool-extract-batch", func() {
|
|
for i := 0; i < b.N; i++ {
|
|
L.GetGlobal("bool_array")
|
|
result, _ := L.BatchExtractBoolArray(-1, 100)
|
|
L.Pop(1)
|
|
_ = result
|
|
}
|
|
})
|
|
})
|
|
}
|