lua对象池管理工具剖析
lua对象池管理工具剖析
- 源码
- 对象池创建函数
- 对象获取机制
- 对象回收机制
- 池清理功能
- 设计模式分析
- 1. 对象池模式
- 2. 享元模式
- 内存管理策略
- 垃圾回收优化
- 使用场景分析
- 1. 网络连接管理
- 2. 游戏对象管理
- 3. 数据库连接池
- 与直接创建方案的对比
一个高效的对象池实现,通过对象复用来减少内存分配和垃圾回收压力,特别适合频繁创建销毁对象的场景
源码
-- object pool, from: https://github.com/treamology/pool.lualocal type, pairs, table, setmetatable = type, pairs, table, setmetatable
local pool = {}
local poolmt = {__index = pool}function pool.create(newObject, poolSize, maxPoolSize)if type(newObject) ~= "function" thenreturn nilendpoolSize = poolSize or 16maxPoolSize = (maxPoolSize and maxPoolSize >= poolSize) and maxPoolSize or 2 * poolSizelocal freeObjects = {}for _ = 1, poolSize dotable.insert(freeObjects, newObject())endreturn setmetatable({freeObjects = freeObjects,newObject = newObject,maxPoolSize = maxPoolSize},poolmt)
endfunction pool:obtain()return #self.freeObjects == 0 and self.newObject() or table.remove(self.freeObjects)
endfunction pool:free(obj, ...)if not obj thenreturn falseendif #self.freeObjects < self.maxPoolSize thentable.insert(self.freeObjects, obj)endif obj.reset then obj.reset(obj, ...) endreturn true
endfunction pool:clear()for k in pairs(self.freeObjects) doself.freeObjects[k] = nilend
endreturn pool
对象池创建函数
function pool.create(newObject, poolSize, maxPoolSize)-- 参数验证:必须提供对象构造函数if type(newObject) ~= "function" thenreturn nilend-- 参数默认值设置poolSize = poolSize or 16maxPoolSize = (maxPoolSize and maxPoolSize >= poolSize) and maxPoolSize or 2 * poolSize-- 预分配对象池local freeObjects = {}for _ = 1, poolSize dotable.insert(freeObjects, newObject())end-- 返回池实例return setmetatable({freeObjects = freeObjects,newObject = newObject,maxPoolSize = maxPoolSize},poolmt)
end
对象获取机制
function pool:obtain()return #self.freeObjects == 0 and self.newObject() or table.remove(self.freeObjects)
end
执行逻辑:
对象回收机制
function pool:free(obj, ...)if not obj thenreturn falseend-- 检查池容量,避免无限增长if #self.freeObjects < self.maxPoolSize thentable.insert(self.freeObjects, obj)end-- 调用对象的reset方法进行清理if obj.reset then obj.reset(obj, ...) endreturn true
end
池清理功能
function pool:clear()for k in pairs(self.freeObjects) doself.freeObjects[k] = nilend
end
设计模式分析
1. 对象池模式
-- 使用示例
local function createConnection()return { id = math.random(1000),connected = false,reset = function(self)self.connected = falseend}
endlocal connectionPool = pool.create(createConnection, 10, 50)
2. 享元模式
通过对象复用,减少相似对象的创建开销
内存管理策略
策略 | 实现方式 | 优势 |
---|---|---|
预分配 | 初始化时创建固定数量对象 | 减少运行时分配 |
动态扩展 | 池空时自动创建新对象 | 避免阻塞 |
容量限制 | maxPoolSize控制内存上限 | 防止内存泄漏 |
垃圾回收优化
-- 传统方式:频繁创建销毁
for i = 1, 1000 dolocal obj = createObject() -- 触发GCuse(obj)-- obj被销毁,GC压力大
end-- 对象池方式:复用对象
for i = 1, 1000 dolocal obj = pool:obtain() -- 从池中获取use(obj)pool:free(obj) -- 放回池中,无GC压力
end
使用场景分析
1. 网络连接管理
local socketPool = pool.create(function()return {fd = nil,status = "closed",reset = function(self)if self.fd thenself:close()endself.status = "closed"end,connect = function(self, host, port)-- 连接逻辑end}
end, 20, 100)
2. 游戏对象管理
local bulletPool = pool.create(function()return {x = 0, y = 0, velocity = 100,active = false,reset = function(self)self.x, self.y = 0, 0self.active = falseend}
end, 50, 200)
3. 数据库连接池
local dbPool = pool.create(function()local conn = mysql.connect(config)return {conn = conn,reset = function(self)-- 重置连接状态self.conn:ping() -- 保持连接活跃end}
end, 5, 20)
与直接创建方案的对比
方面 | 对象池 | 直接创建 |
---|---|---|
内存分配 | 预分配+复用 | 每次新建 |
GC压力 | 极小 | 频繁触发 |
初始化成本 | 一次性 | 每次都有 |
灵活性 | 需要reset逻辑 | 无需特殊处理 |