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