250 lines
6.2 KiB
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() |