Moonshark/benchmarks/string.lua

250 lines
6.2 KiB
Lua

require("../tests/tests")
local str = require("string")
-- Pure Lua implementations for comparison
local pure_lua = {}
function pure_lua.capitalize(s)
return s:gsub("(%a)([%w_']*)", function(first, rest)
return first:upper() .. rest:lower()
end)
end
function pure_lua.camel_case(s)
local words = {}
for word in s:gmatch("%S+") do
table.insert(words, word:lower())
end
if #words == 0 then return s end
local result = words[1]
for i = 2, #words do
result = result .. words[i]:gsub("^%l", string.upper)
end
return result
end
function pure_lua.template(template, vars)
vars = vars or {}
return template:gsub("%${([%w_]+)}", function(var)
return tostring(vars[var] or "")
end)
end
function pure_lua.distance(a, b)
local len_a, len_b = #a, #b
if len_a == 0 then return len_b end
if len_b == 0 then return len_a end
local matrix = {}
for i = 0, len_a do
matrix[i] = {[0] = i}
end
for j = 0, len_b do
matrix[0][j] = j
end
for i = 1, len_a do
for j = 1, len_b do
local cost = (a:sub(i,i) == b:sub(j,j)) and 0 or 1
matrix[i][j] = math.min(
matrix[i-1][j] + 1,
matrix[i][j-1] + 1,
matrix[i-1][j-1] + cost
)
end
end
return matrix[len_a][len_b]
end
function pure_lua.wrap(s, width)
local words = {}
for word in s:gmatch("%S+") do
table.insert(words, word)
end
local lines = {}
local current_line = ""
for _, word in ipairs(words) do
if #current_line + #word + 1 <= width then
if current_line == "" then
current_line = word
else
current_line = current_line .. " " .. word
end
else
if current_line ~= "" then
table.insert(lines, current_line)
end
current_line = word
end
end
if current_line ~= "" then
table.insert(lines, current_line)
end
return lines
end
function pure_lua.slug(s)
-- Remove accents (simplified)
local result = s:lower()
result = result:gsub("[àáâãäå]", "a")
result = result:gsub("[èéêë]", "e")
result = result:gsub("[ìíîï]", "i")
result = result:gsub("[òóôõö]", "o")
result = result:gsub("[ùúûü]", "u")
result = result:gsub("[ñ]", "n")
result = result:gsub("[ç]", "c")
result = result:gsub("[^%w%s]", "")
result = result:gsub("%s+", "-")
result = result:gsub("^%-+", ""):gsub("%-+$", "")
return result
end
-- Test data
local test_texts = {
short = "Hello World",
medium = "The quick brown fox jumps over the lazy dog. This is a test sentence for benchmarking.",
long = string.rep("Lorem ipsum dolor sit amet, consectetur adipiscing elit. ", 100),
template_str = "Hello ${name}, you are ${age} years old and work as a ${job}.",
template_vars = {name = "John", age = 30, job = "developer"}
}
-- Benchmark function
local function benchmark_comparison(name, go_func, lua_func, test_data, iterations)
iterations = iterations or 10000
print(string.format("\n=== %s Benchmark (%d iterations) ===", name, iterations))
-- Warmup
for i = 1, 100 do
go_func(test_data)
lua_func(test_data)
end
-- Benchmark Go version
local go_start = os.clock()
for i = 1, iterations do
go_func(test_data)
end
local go_time = os.clock() - go_start
-- Benchmark Lua version
local lua_start = os.clock()
for i = 1, iterations do
lua_func(test_data)
end
local lua_time = os.clock() - lua_start
-- Results
local go_rate = iterations / go_time
local lua_rate = iterations / lua_time
local speedup = lua_time / go_time
print(string.format("Go (enhanced): %.3fs (%.0f ops/sec)", go_time, go_rate))
print(string.format("Lua (pure): %.3fs (%.0f ops/sec)", lua_time, lua_rate))
print(string.format("Speedup: %.2fx %s", math.abs(speedup), speedup > 1 and "(Go faster)" or "(Lua faster)"))
return {
go_time = go_time,
lua_time = lua_time,
speedup = speedup,
go_rate = go_rate,
lua_rate = lua_rate
}
end
-- Benchmark wrapper functions
local function run_benchmarks()
print("String Operations Performance Comparison")
print("=" .. string.rep("=", 50))
local results = {}
-- Capitalize benchmark
results.capitalize = benchmark_comparison(
"Capitalize",
function(text) return str.capitalize(text) end,
function(text) return pure_lua.capitalize(text) end,
test_texts.medium
)
-- CamelCase benchmark
results.camel_case = benchmark_comparison(
"CamelCase",
function(text) return str.camel_case(text) end,
function(text) return pure_lua.camel_case(text) end,
test_texts.medium
)
-- Template benchmark
results.template = benchmark_comparison(
"Template",
function(data) return str.template(test_texts.template_str, data) end,
function(data) return pure_lua.template(test_texts.template_str, data) end,
test_texts.template_vars
)
-- Distance benchmark (shorter strings due to O(n²) complexity)
results.distance = benchmark_comparison(
"Levenshtein Distance",
function(texts) return str.distance(texts[1], texts[2]) end,
function(texts) return pure_lua.distance(texts[1], texts[2]) end,
{"kitten", "sitting"},
1000 -- Fewer iterations for expensive operation
)
-- Wrap benchmark
results.wrap = benchmark_comparison(
"Text Wrap",
function(text) return str.wrap(text, 40) end,
function(text) return pure_lua.wrap(text, 40) end,
test_texts.long
)
-- Slug benchmark
results.slug = benchmark_comparison(
"Slug Generation",
function(text) return str.slug(text) end,
function(text) return pure_lua.slug(text) end,
"Café & Restaurant!! Special Characters"
)
-- Summary
print("\n" .. string.rep("=", 50))
print("PERFORMANCE SUMMARY")
print(string.rep("=", 50))
local go_wins = 0
local lua_wins = 0
for name, result in pairs(results) do
local winner = result.speedup > 1 and "Go" or "Lua"
local margin = string.format("%.2fx", math.abs(result.speedup))
print(string.format("%-20s: %s wins by %s", name, winner, margin))
if result.speedup > 1 then
go_wins = go_wins + 1
else
lua_wins = lua_wins + 1
end
end
print(string.rep("-", 50))
print(string.format("Go wins: %d, Lua wins: %d", go_wins, lua_wins))
-- Analysis
print("\nANALYSIS:")
print("• Go functions benefit from optimized implementations")
print("• Lua functions avoid CGO overhead for simple operations")
print("• Choice depends on operation complexity vs call frequency")
return results
end
-- Run the benchmarks
run_benchmarks()