Lua调试和性能优化
概述
调试和性能优化是软件开发中的重要环节。Lua提供了强大的调试库和性能分析工具,本文档将介绍如何有效地调试Lua程序和优化其性能。
1. 调试基础
1.1 debug库简介
Lua的debug库提供了丰富的调试功能,包括获取调用栈信息、检查局部变量、设置钩子函数等。
lua
-- debug库基本功能演示
local function debug_basics()
print("=== debug库基础功能 ===")
local function inner_function(a, b)
local c = a + b
local d = a * b
-- 获取当前函数信息
local info = debug.getinfo(1, "nSl")
print("函数名:", info.name or "匿名函数")
print("文件:", info.source)
print("当前行:", info.currentline)
print("函数定义行:", info.linedefined)
-- 获取局部变量
print("\n局部变量:")
local i = 1
while true do
local name, value = debug.getlocal(1, i)
if not name then break end
print(string.format(" %s = %s", name, tostring(value)))
i = i + 1
end
-- 获取上值(upvalue)
print("\n上值:")
i = 1
while true do
local name, value = debug.getupvalue(inner_function, i)
if not name then break end
print(string.format(" %s = %s", name, tostring(value)))
i = i + 1
end
return c, d
end
local result1, result2 = inner_function(10, 5)
print("\n结果:", result1, result2)
end
debug_basics()1.2 调用栈跟踪
lua
-- 调用栈跟踪
local function stack_trace_demo()
print("\n=== 调用栈跟踪 ===")
local function level3()
print("Level 3 - 调用栈信息:")
print(debug.traceback())
-- 手动遍历调用栈
print("\n手动遍历调用栈:")
local level = 1
while true do
local info = debug.getinfo(level, "nSl")
if not info then break end
print(string.format("Level %d: %s (%s:%d)",
level,
info.name or "匿名函数",
info.source or "unknown",
info.currentline or 0))
level = level + 1
end
end
local function level2()
level3()
end
local function level1()
level2()
end
level1()
end
stack_trace_demo()1.3 变量监控和修改
lua
-- 变量监控和修改
local function variable_monitoring()
print("\n=== 变量监控和修改 ===")
local function test_function()
local x = 10
local y = 20
local z = x + y
print("修改前:", x, y, z)
-- 在运行时修改局部变量
debug.setlocal(1, 1, 100) -- 修改第1个局部变量 x
debug.setlocal(1, 2, 200) -- 修改第2个局部变量 y
-- 重新计算
z = x + y
print("修改后:", x, y, z)
return z
end
local result = test_function()
print("最终结果:", result)
end
variable_monitoring()2. 高级调试技术
2.1 调试钩子
lua
-- 调试钩子系统
local DebugHook = {}
DebugHook.__index = DebugHook
function DebugHook.new()
return setmetatable({
enabled = false,
call_count = 0,
line_count = 0,
return_count = 0,
call_stack = {},
line_history = {}
}, DebugHook)
end
function DebugHook:enable()
if self.enabled then return end
self.enabled = true
debug.sethook(function(event, line)
self:handle_event(event, line)
end, "clr")
print("调试钩子已启用")
end
function DebugHook:disable()
if not self.enabled then return end
self.enabled = false
debug.sethook()
print("调试钩子已禁用")
end
function DebugHook:handle_event(event, line)
if event == "call" then
self.call_count = self.call_count + 1
local info = debug.getinfo(2, "nS")
local func_name = info.name or "匿名函数"
table.insert(self.call_stack, func_name)
print(string.format("CALL: %s (调用次数: %d)", func_name, self.call_count))
elseif event == "return" then
self.return_count = self.return_count + 1
local func_name = table.remove(self.call_stack) or "未知函数"
print(string.format("RETURN: %s (返回次数: %d)", func_name, self.return_count))
elseif event == "line" then
self.line_count = self.line_count + 1
local info = debug.getinfo(2, "S")
local source = info.source or "unknown"
-- 只记录最近的100行
if #self.line_history >= 100 then
table.remove(self.line_history, 1)
end
table.insert(self.line_history, {source = source, line = line})
-- 每100行打印一次统计
if self.line_count % 100 == 0 then
print(string.format("LINE: 已执行 %d 行", self.line_count))
end
end
end
function DebugHook:get_statistics()
return {
call_count = self.call_count,
return_count = self.return_count,
line_count = self.line_count,
stack_depth = #self.call_stack
}
end
function DebugHook:print_statistics()
local stats = self:get_statistics()
print("\n=== 调试统计 ===")
print("函数调用次数:", stats.call_count)
print("函数返回次数:", stats.return_count)
print("执行行数:", stats.line_count)
print("当前调用栈深度:", stats.stack_depth)
if #self.call_stack > 0 then
print("当前调用栈:")
for i, func_name in ipairs(self.call_stack) do
print(" " .. i .. ": " .. func_name)
end
end
end
-- 调试钩子示例
local function debug_hook_example()
print("\n=== 调试钩子示例 ===")
local hook = DebugHook.new()
hook:enable()
-- 测试函数
local function fibonacci(n)
if n <= 1 then
return n
end
return fibonacci(n - 1) + fibonacci(n - 2)
end
local function test_recursive()
local result = fibonacci(8)
print("斐波那契(8) =", result)
return result
end
test_recursive()
hook:disable()
hook:print_statistics()
end
debug_hook_example()2.2 断点系统
lua
-- 简单的断点系统
local Breakpoint = {}
Breakpoint.__index = Breakpoint
function Breakpoint.new()
return setmetatable({
breakpoints = {},
enabled = false,
step_mode = false
}, Breakpoint)
end
function Breakpoint:add(source, line)
local key = source .. ":" .. line
self.breakpoints[key] = true
print(string.format("添加断点: %s:%d", source, line))
end
function Breakpoint:remove(source, line)
local key = source .. ":" .. line
self.breakpoints[key] = nil
print(string.format("移除断点: %s:%d", source, line))
end
function Breakpoint:enable()
if self.enabled then return end
self.enabled = true
debug.sethook(function(event, line)
if event == "line" then
self:check_breakpoint(line)
end
end, "l")
print("断点系统已启用")
end
function Breakpoint:disable()
if not self.enabled then return end
self.enabled = false
debug.sethook()
print("断点系统已禁用")
end
function Breakpoint:check_breakpoint(line)
local info = debug.getinfo(2, "S")
local source = info.source or "unknown"
local key = source .. ":" .. line
if self.breakpoints[key] or self.step_mode then
self:hit_breakpoint(source, line)
end
end
function Breakpoint:hit_breakpoint(source, line)
print(string.format("\n断点命中: %s:%d", source, line))
-- 显示当前上下文
self:show_context()
-- 简单的调试命令循环
while true do
io.write("(debug) ")
local command = io.read()
if command == "c" or command == "continue" then
self.step_mode = false
break
elseif command == "s" or command == "step" then
self.step_mode = true
break
elseif command == "l" or command == "locals" then
self:show_locals()
elseif command == "bt" or command == "backtrace" then
print(debug.traceback())
elseif command == "h" or command == "help" then
self:show_help()
elseif command == "q" or command == "quit" then
self:disable()
break
else
print("未知命令,输入 'h' 查看帮助")
end
end
end
function Breakpoint:show_context()
local info = debug.getinfo(2, "nSl")
print("函数:", info.name or "匿名函数")
print("文件:", info.source or "unknown")
print("行号:", info.currentline or "unknown")
end
function Breakpoint:show_locals()
print("局部变量:")
local level = 2
local i = 1
while true do
local name, value = debug.getlocal(level, i)
if not name then break end
print(string.format(" %s = %s (%s)", name, tostring(value), type(value)))
i = i + 1
end
end
function Breakpoint:show_help()
print("调试命令:")
print(" c, continue - 继续执行")
print(" s, step - 单步执行")
print(" l, locals - 显示局部变量")
print(" bt, backtrace - 显示调用栈")
print(" h, help - 显示帮助")
print(" q, quit - 退出调试")
end
-- 断点系统示例(注释掉交互部分)
local function breakpoint_example()
print("\n=== 断点系统示例 ===")
local bp = Breakpoint.new()
-- 这里我们不能真正设置断点,因为我们不知道确切的源文件
-- 在实际使用中,你会这样做:
-- bp:add("@/path/to/your/script.lua", 10)
print("断点系统已创建(示例中不启用交互模式)")
print("在实际使用中,你可以:")
print("1. bp:add(source, line) - 添加断点")
print("2. bp:enable() - 启用断点系统")
print("3. 运行你的代码")
print("4. 在断点处使用调试命令")
end
breakpoint_example()3. 性能分析
3.1 时间性能分析
lua
-- 性能分析器
local Profiler = {}
Profiler.__index = Profiler
function Profiler.new()
return setmetatable({
functions = {},
call_stack = {},
start_time = nil
}, Profiler)
end
function Profiler:start()
self.start_time = os.clock()
debug.sethook(function(event)
self:handle_event(event)
end, "cr")
print("性能分析器已启动")
end
function Profiler:stop()
debug.sethook()
local total_time = os.clock() - self.start_time
print(string.format("性能分析器已停止,总时间: %.4f 秒", total_time))
return self:get_report()
end
function Profiler:handle_event(event)
local info = debug.getinfo(2, "nS")
local func_name = self:get_function_name(info)
local current_time = os.clock()
if event == "call" then
-- 记录函数调用开始时间
table.insert(self.call_stack, {
name = func_name,
start_time = current_time
})
if not self.functions[func_name] then
self.functions[func_name] = {
call_count = 0,
total_time = 0,
self_time = 0
}
end
self.functions[func_name].call_count = self.functions[func_name].call_count + 1
elseif event == "return" then
-- 计算函数执行时间
local call_info = table.remove(self.call_stack)
if call_info and call_info.name == func_name then
local elapsed = current_time - call_info.start_time
self.functions[func_name].total_time = self.functions[func_name].total_time + elapsed
end
end
end
function Profiler:get_function_name(info)
if info.name then
return info.name
elseif info.source and info.linedefined then
return string.format("%s:%d", info.source, info.linedefined)
else
return "匿名函数"
end
end
function Profiler:get_report()
local report = {}
for func_name, stats in pairs(self.functions) do
table.insert(report, {
name = func_name,
call_count = stats.call_count,
total_time = stats.total_time,
avg_time = stats.total_time / stats.call_count
})
end
-- 按总时间排序
table.sort(report, function(a, b)
return a.total_time > b.total_time
end)
return report
end
function Profiler:print_report(report)
print("\n=== 性能分析报告 ===")
print(string.format("%-30s %10s %12s %12s", "函数名", "调用次数", "总时间(s)", "平均时间(s)"))
print(string.rep("-", 70))
for _, stats in ipairs(report) do
print(string.format("%-30s %10d %12.6f %12.6f",
stats.name:sub(1, 30),
stats.call_count,
stats.total_time,
stats.avg_time
))
end
end
-- 性能分析示例
local function profiling_example()
print("\n=== 性能分析示例 ===")
local profiler = Profiler.new()
-- 测试函数
local function slow_function()
local sum = 0
for i = 1, 100000 do
sum = sum + i
end
return sum
end
local function fast_function()
return 100000 * 100001 / 2
end
local function mixed_function()
local result1 = slow_function()
local result2 = fast_function()
return result1 + result2
end
profiler:start()
-- 执行测试
for i = 1, 10 do
mixed_function()
end
local report = profiler:stop()
profiler:print_report(report)
end
profiling_example()3.2 内存使用分析
lua
-- 内存分析器
local MemoryProfiler = {}
MemoryProfiler.__index = MemoryProfiler
function MemoryProfiler.new()
return setmetatable({
snapshots = {},
allocations = {}
}, MemoryProfiler)
end
function MemoryProfiler:take_snapshot(name)
collectgarbage("collect") -- 强制垃圾回收
local memory = collectgarbage("count")
self.snapshots[name] = {
memory = memory,
timestamp = os.time()
}
print(string.format("内存快照 '%s': %.2f KB", name, memory))
return memory
end
function MemoryProfiler:compare_snapshots(name1, name2)
local snap1 = self.snapshots[name1]
local snap2 = self.snapshots[name2]
if not snap1 or not snap2 then
error("快照不存在")
end
local diff = snap2.memory - snap1.memory
print(string.format("内存变化 (%s -> %s): %.2f KB", name1, name2, diff))
return diff
end
function MemoryProfiler:get_memory_info()
collectgarbage("collect")
local info = {
used = collectgarbage("count"),
threshold = collectgarbage("count") * 2, -- 近似阈值
collections = 0 -- Lua没有直接获取GC次数的方法
}
return info
end
function MemoryProfiler:print_memory_info()
local info = self:get_memory_info()
print("\n=== 内存信息 ===")
print(string.format("已使用内存: %.2f KB", info.used))
print(string.format("GC阈值(估算): %.2f KB", info.threshold))
end
function MemoryProfiler:monitor_allocations(func, name)
local before = self:take_snapshot(name .. "_before")
local start_time = os.clock()
local result = func()
local end_time = os.clock()
local after = self:take_snapshot(name .. "_after")
local diff = self:compare_snapshots(name .. "_before", name .. "_after")
self.allocations[name] = {
memory_diff = diff,
execution_time = end_time - start_time,
result = result
}
return result
end
function MemoryProfiler:print_allocation_report()
print("\n=== 内存分配报告 ===")
print(string.format("%-20s %15s %15s", "操作", "内存变化(KB)", "执行时间(s)"))
print(string.rep("-", 55))
for name, info in pairs(self.allocations) do
print(string.format("%-20s %15.2f %15.6f",
name, info.memory_diff, info.execution_time))
end
end
-- 内存分析示例
local function memory_profiling_example()
print("\n=== 内存分析示例 ===")
local profiler = MemoryProfiler.new()
profiler:print_memory_info()
-- 测试大量字符串创建
profiler:monitor_allocations(function()
local strings = {}
for i = 1, 10000 do
strings[i] = "string_" .. i
end
return #strings
end, "string_creation")
-- 测试大量表创建
profiler:monitor_allocations(function()
local tables = {}
for i = 1, 1000 do
tables[i] = {id = i, name = "item_" .. i, data = {}}
end
return #tables
end, "table_creation")
-- 测试函数创建
profiler:monitor_allocations(function()
local functions = {}
for i = 1, 1000 do
functions[i] = function() return i end
end
return #functions
end, "function_creation")
profiler:print_allocation_report()
profiler:print_memory_info()
end
memory_profiling_example()4. 性能优化技术
4.1 算法优化
lua
-- 算法优化示例
local function algorithm_optimization()
print("\n=== 算法优化示例 ===")
-- 低效的斐波那契实现
local function fibonacci_naive(n)
if n <= 1 then return n end
return fibonacci_naive(n - 1) + fibonacci_naive(n - 2)
end
-- 带记忆化的斐波那契实现
local function fibonacci_memoized()
local cache = {}
local function fib(n)
if cache[n] then
return cache[n]
end
local result
if n <= 1 then
result = n
else
result = fib(n - 1) + fib(n - 2)
end
cache[n] = result
return result
end
return fib
end
-- 迭代版本的斐波那契
local function fibonacci_iterative(n)
if n <= 1 then return n end
local a, b = 0, 1
for i = 2, n do
a, b = b, a + b
end
return b
end
-- 性能测试
local function time_function(func, n, name)
local start_time = os.clock()
local result = func(n)
local end_time = os.clock()
print(string.format("%s(%d) = %d, 时间: %.6f 秒",
name, n, result, end_time - start_time))
return end_time - start_time
end
local n = 35
print(string.format("计算斐波那契数列第 %d 项:", n))
-- 只测试小数值的朴素版本,避免等待太久
if n <= 35 then
time_function(fibonacci_naive, n, "朴素递归")
end
local fib_memo = fibonacci_memoized()
time_function(fib_memo, n, "记忆化递归")
time_function(fibonacci_iterative, n, "迭代版本")
end
algorithm_optimization()4.2 数据结构优化
lua
-- 数据结构优化示例
local function data_structure_optimization()
print("\n=== 数据结构优化示例 ===")
-- 低效的查找实现(数组线性查找)
local function array_search(array, target)
for i, value in ipairs(array) do
if value == target then
return i
end
end
return nil
end
-- 高效的查找实现(哈希表)
local function hash_search(hash_table, target)
return hash_table[target]
end
-- 创建测试数据
local size = 10000
local test_array = {}
local test_hash = {}
for i = 1, size do
local value = "item_" .. i
test_array[i] = value
test_hash[value] = i
end
local target = "item_" .. math.floor(size * 0.8) -- 查找80%位置的元素
-- 性能测试
local function benchmark_search(search_func, data, target, name)
local start_time = os.clock()
local result = search_func(data, target)
local end_time = os.clock()
print(string.format("%s: 找到 %s 在位置 %s, 时间: %.6f 秒",
name, target, tostring(result), end_time - start_time))
end
benchmark_search(array_search, test_array, target, "数组线性查找")
benchmark_search(hash_search, test_hash, target, "哈希表查找")
end
data_structure_optimization()4.3 字符串优化
lua
-- 字符串操作优化
local function string_optimization()
print("\n=== 字符串优化示例 ===")
-- 低效的字符串连接
local function inefficient_concat(n)
local result = ""
for i = 1, n do
result = result .. "item" .. i .. ","
end
return result
end
-- 高效的字符串连接
local function efficient_concat(n)
local parts = {}
for i = 1, n do
parts[i] = "item" .. i
end
return table.concat(parts, ",")
end
-- 使用缓冲区的字符串连接
local function buffer_concat(n)
local buffer = {}
local index = 1
for i = 1, n do
buffer[index] = "item"
buffer[index + 1] = tostring(i)
buffer[index + 2] = ","
index = index + 3
end
return table.concat(buffer)
end
-- 性能测试
local function benchmark_concat(func, n, name)
local start_time = os.clock()
local result = func(n)
local end_time = os.clock()
print(string.format("%s (%d items): %.6f 秒, 结果长度: %d",
name, n, end_time - start_time, #result))
end
local n = 5000
benchmark_concat(inefficient_concat, n, "低效连接")
benchmark_concat(efficient_concat, n, "table.concat")
benchmark_concat(buffer_concat, n, "缓冲区连接")
end
string_optimization()4.4 循环优化
lua
-- 循环优化示例
local function loop_optimization()
print("\n=== 循环优化示例 ===")
local size = 1000000
local data = {}
for i = 1, size do
data[i] = i
end
-- 低效的循环(重复计算长度)
local function inefficient_loop(array)
local sum = 0
for i = 1, #array do -- 每次都计算#array
sum = sum + array[i]
end
return sum
end
-- 优化的循环(缓存长度)
local function optimized_loop(array)
local sum = 0
local len = #array -- 只计算一次长度
for i = 1, len do
sum = sum + array[i]
end
return sum
end
-- 使用ipairs的循环
local function ipairs_loop(array)
local sum = 0
for i, value in ipairs(array) do
sum = sum + value
end
return sum
end
-- 使用数值for循环(最优化)
local function numeric_loop(array)
local sum = 0
for i = 1, #array do
sum = sum + array[i]
end
return sum
end
-- 性能测试
local function benchmark_loop(func, data, name)
local start_time = os.clock()
local result = func(data)
local end_time = os.clock()
print(string.format("%s: 结果 %d, 时间: %.6f 秒",
name, result, end_time - start_time))
end
benchmark_loop(inefficient_loop, data, "低效循环")
benchmark_loop(optimized_loop, data, "优化循环")
benchmark_loop(ipairs_loop, data, "ipairs循环")
benchmark_loop(numeric_loop, data, "数值循环")
end
loop_optimization()5. 内存优化
5.1 垃圾回收优化
lua
-- 垃圾回收优化
local function gc_optimization()
print("\n=== 垃圾回收优化 ===")
-- 获取GC信息
local function print_gc_info(label)
collectgarbage("collect")
local memory = collectgarbage("count")
print(string.format("%s: 内存使用 %.2f KB", label, memory))
end
print_gc_info("初始状态")
-- 创建大量临时对象
local function create_garbage()
local objects = {}
for i = 1, 100000 do
objects[i] = {
id = i,
name = "object_" .. i,
data = string.rep("x", 100)
}
end
return #objects
end
local count = create_garbage()
print_gc_info("创建对象后")
-- 手动触发垃圾回收
collectgarbage("collect")
print_gc_info("手动GC后")
-- 调整GC参数
local old_pause = collectgarbage("setpause", 200) -- 设置GC暂停时间
local old_stepmul = collectgarbage("setstepmul", 400) -- 设置GC步进倍数
print(string.format("GC参数调整: pause %d->200, stepmul %d->400",
old_pause, old_stepmul))
-- 恢复原始参数
collectgarbage("setpause", old_pause)
collectgarbage("setstepmul", old_stepmul)
print("GC参数已恢复")
end
gc_optimization()5.2 对象池模式
lua
-- 对象池实现
local ObjectPool = {}
ObjectPool.__index = ObjectPool
function ObjectPool.new(create_func, reset_func, initial_size)
local pool = setmetatable({
create_func = create_func,
reset_func = reset_func,
available = {},
in_use = {},
total_created = 0,
total_reused = 0
}, ObjectPool)
-- 预创建对象
for i = 1, (initial_size or 10) do
local obj = create_func()
table.insert(pool.available, obj)
pool.total_created = pool.total_created + 1
end
return pool
end
function ObjectPool:acquire()
local obj
if #self.available > 0 then
obj = table.remove(self.available)
self.total_reused = self.total_reused + 1
else
obj = self.create_func()
self.total_created = self.total_created + 1
end
self.in_use[obj] = true
return obj
end
function ObjectPool:release(obj)
if not self.in_use[obj] then
error("对象不在使用中")
end
self.in_use[obj] = nil
if self.reset_func then
self.reset_func(obj)
end
table.insert(self.available, obj)
end
function ObjectPool:get_stats()
return {
available = #self.available,
in_use = self:count_in_use(),
total_created = self.total_created,
total_reused = self.total_reused,
reuse_rate = self.total_reused / (self.total_created + self.total_reused)
}
end
function ObjectPool:count_in_use()
local count = 0
for _ in pairs(self.in_use) do
count = count + 1
end
return count
end
-- 对象池示例
local function object_pool_example()
print("\n=== 对象池示例 ===")
-- 创建字符串缓冲区对象池
local function create_buffer()
return {data = {}, length = 0}
end
local function reset_buffer(buffer)
for i = 1, buffer.length do
buffer.data[i] = nil
end
buffer.length = 0
end
local pool = ObjectPool.new(create_buffer, reset_buffer, 5)
-- 模拟使用对象池
local buffers = {}
-- 获取多个对象
for i = 1, 10 do
local buffer = pool:acquire()
buffer.data[1] = "data_" .. i
buffer.length = 1
buffers[i] = buffer
end
local stats = pool:get_stats()
print(string.format("获取10个对象后: 可用 %d, 使用中 %d, 总创建 %d",
stats.available, stats.in_use, stats.total_created))
-- 释放一半对象
for i = 1, 5 do
pool:release(buffers[i])
buffers[i] = nil
end
stats = pool:get_stats()
print(string.format("释放5个对象后: 可用 %d, 使用中 %d, 重用率 %.2f%%",
stats.available, stats.in_use, stats.reuse_rate * 100))
-- 再次获取对象(应该重用)
for i = 6, 10 do
local buffer = pool:acquire()
buffers[i] = buffer
end
stats = pool:get_stats()
print(string.format("再次获取5个对象后: 总重用 %d, 重用率 %.2f%%",
stats.total_reused, stats.reuse_rate * 100))
end
object_pool_example()6. 最佳实践
6.1 性能测试框架
lua
-- 简单的性能测试框架
local Benchmark = {}
Benchmark.__index = Benchmark
function Benchmark.new(name)
return setmetatable({
name = name or "Benchmark",
tests = {},
results = {}
}, Benchmark)
end
function Benchmark:add_test(name, func, setup, teardown)
table.insert(self.tests, {
name = name,
func = func,
setup = setup,
teardown = teardown
})
end
function Benchmark:run(iterations)
iterations = iterations or 1000
print(string.format("\n=== %s (每个测试 %d 次迭代) ===", self.name, iterations))
for _, test in ipairs(self.tests) do
-- 设置
if test.setup then
test.setup()
end
-- 预热
for i = 1, math.min(100, iterations) do
test.func()
end
-- 正式测试
collectgarbage("collect")
local start_memory = collectgarbage("count")
local start_time = os.clock()
for i = 1, iterations do
test.func()
end
local end_time = os.clock()
collectgarbage("collect")
local end_memory = collectgarbage("count")
local total_time = end_time - start_time
local avg_time = total_time / iterations
local memory_diff = end_memory - start_memory
self.results[test.name] = {
total_time = total_time,
avg_time = avg_time,
memory_diff = memory_diff,
iterations = iterations
}
print(string.format("%-20s: 总时间 %.6fs, 平均 %.9fs, 内存变化 %.2fKB",
test.name, total_time, avg_time, memory_diff))
-- 清理
if test.teardown then
test.teardown()
end
end
end
function Benchmark:compare()
if #self.results < 2 then
print("需要至少2个测试结果才能比较")
return
end
print("\n=== 性能比较 ===")
-- 找到最快的测试
local fastest = nil
local fastest_time = math.huge
for name, result in pairs(self.results) do
if result.avg_time < fastest_time then
fastest = name
fastest_time = result.avg_time
end
end
-- 与最快的测试比较
for name, result in pairs(self.results) do
if name ~= fastest then
local ratio = result.avg_time / fastest_time
print(string.format("%s 比 %s 慢 %.2f 倍", name, fastest, ratio))
end
end
end
-- 性能测试示例
local function benchmark_example()
print("\n=== 性能测试框架示例 ===")
local bench = Benchmark.new("字符串操作性能测试")
local test_data = {}
for i = 1, 100 do
test_data[i] = "string_" .. i
end
-- 添加测试用例
bench:add_test("string.concat", function()
local result = ""
for _, str in ipairs(test_data) do
result = result .. str
end
return result
end)
bench:add_test("table.concat", function()
return table.concat(test_data)
end)
bench:add_test("table.concat_with_sep", function()
return table.concat(test_data, ",")
end)
-- 运行测试
bench:run(1000)
bench:compare()
end
benchmark_example()6.2 调试最佳实践
lua
-- 调试最佳实践示例
local function debugging_best_practices()
print("\n=== 调试最佳实践 ===")
-- 1. 使用断言进行参数验证
local function safe_divide(a, b)
assert(type(a) == "number", "第一个参数必须是数字")
assert(type(b) == "number", "第二个参数必须是数字")
assert(b ~= 0, "除数不能为零")
return a / b
end
-- 2. 使用日志记录关键信息
local function log(level, message, ...)
local timestamp = os.date("%Y-%m-%d %H:%M:%S")
local formatted_message = string.format(message, ...)
print(string.format("[%s] %s: %s", timestamp, level, formatted_message))
end
-- 3. 错误处理和恢复
local function robust_operation(data)
local success, result = pcall(function()
-- 可能出错的操作
if not data or #data == 0 then
error("数据为空")
end
local sum = 0
for _, value in ipairs(data) do
sum = sum + value
end
return sum
end)
if success then
log("INFO", "操作成功,结果: %s", result)
return result
else
log("ERROR", "操作失败: %s", result)
return nil, result
end
end
-- 4. 调试信息的条件输出
local DEBUG = true
local function debug_print(...)
if DEBUG then
print("[DEBUG]", ...)
end
end
-- 示例使用
print("1. 参数验证:")
local success, result = pcall(safe_divide, 10, 2)
print("结果:", success and result or result)
success, result = pcall(safe_divide, 10, 0)
print("错误:", success and result or result)
print("\n2. 日志记录:")
log("INFO", "程序启动")
log("WARN", "内存使用率: %d%%", 75)
log("ERROR", "连接失败,重试次数: %d", 3)
print("\n3. 错误处理:")
local data1 = {1, 2, 3, 4, 5}
local data2 = {}
robust_operation(data1)
robust_operation(data2)
print("\n4. 调试输出:")
debug_print("这是调试信息")
DEBUG = false
debug_print("这不会显示")
end
debugging_best_practices()总结
Lua调试和性能优化的关键要点:
调试技术
- debug库 - 提供强大的运行时检查能力
- 调用栈跟踪 - 帮助定位问题源头
- 变量监控 - 实时查看和修改变量值
- 调试钩子 - 监控程序执行流程
- 断点系统 - 精确控制程序执行
性能分析
- 时间分析 - 识别性能瓶颈函数
- 内存分析 - 监控内存使用和泄漏
- 算法优化 - 选择更高效的算法
- 数据结构优化 - 使用合适的数据结构
优化策略
- 算法层面 - 减少时间复杂度
- 数据结构 - 选择高效的存储方式
- 字符串操作 - 避免频繁的字符串连接
- 循环优化 - 减少不必要的计算
- 内存管理 - 合理使用对象池和垃圾回收
最佳实践
- 性能测试 - 建立基准测试
- 调试工具 - 使用合适的调试方法
- 错误处理 - 健壮的错误处理机制
- 代码质量 - 保持代码的可读性和可维护性
通过掌握这些调试和优化技术,可以开发出高质量、高性能的Lua应用程序。