Skip to content

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调试和性能优化的关键要点:

调试技术

  1. debug库 - 提供强大的运行时检查能力
  2. 调用栈跟踪 - 帮助定位问题源头
  3. 变量监控 - 实时查看和修改变量值
  4. 调试钩子 - 监控程序执行流程
  5. 断点系统 - 精确控制程序执行

性能分析

  1. 时间分析 - 识别性能瓶颈函数
  2. 内存分析 - 监控内存使用和泄漏
  3. 算法优化 - 选择更高效的算法
  4. 数据结构优化 - 使用合适的数据结构

优化策略

  1. 算法层面 - 减少时间复杂度
  2. 数据结构 - 选择高效的存储方式
  3. 字符串操作 - 避免频繁的字符串连接
  4. 循环优化 - 减少不必要的计算
  5. 内存管理 - 合理使用对象池和垃圾回收

最佳实践

  1. 性能测试 - 建立基准测试
  2. 调试工具 - 使用合适的调试方法
  3. 错误处理 - 健壮的错误处理机制
  4. 代码质量 - 保持代码的可读性和可维护性

通过掌握这些调试和优化技术,可以开发出高质量、高性能的Lua应用程序。

基于 MIT 许可发布