Corona SDK / Lua / 内存泄漏
Corona SDK / Lua / memory leak
所以我有一个正在开发的游戏的 rain 模块,它会导致大量系统内存泄漏,从而导致延迟并最终导致应用程序崩溃。
函数 "t.start" 每 50 毫秒用定时器调用一次。
虽然我试过了,但我真的找不到原因!也许我忽略了一些东西,但我无能为力。如您所见,我删除了与当地人相关的图形...有人注意到什么了吗?
作为次要问题:有没有人有关于预加载下一个场景以平滑场景切换的提示?因为当我把它放在 "scene:show()"...
时,加载本身会导致短暂的冻结
感谢您的帮助!
你好,尼尔斯
local t = {}
local composer = require("composer")
t.drops = {}
function t.fall(drops, group)
for i = 1, #drops, 1 do
local thisDrop = drops[i]
function thisDrop:enterFrame()
if aboutToBeDestroyed == true then
Runtime:removeEventListener("enterFrame", self)
return true
end
local randomY = math.random(32, 64)
if self.x ~= nil then
self:translate(0, randomY)
if self.y > 2000 then
self:removeSelf()
Runtime:removeEventListener("enterFrame", self)
self = nil
end
end
end
Runtime:addEventListener("enterFrame", drops[i])
thisDrop = nil
end
end
t.clean = function()
for i = 1, #t.drops, 1 do
if t.drops[i] ~= nil then
table.remove(t.drops, i)
t.drops[i] = nil
end
end
end
function t.start(group)
local drops = {}
local theGroup = group
for i = 1, 20, 1 do
local randomWidth = math.random(5, 30)
local dropV = display.newRect(group, 1, 1, randomWidth, 30)
local drop1 = display.newSnapshot(dropV.contentWidth , dropV.contentHeight * 3)
drop1.canvas:insert(dropV)
drop1.fill.effect = "filter.blurVertical"
drop1.fill.effect.blurSize = 30
drop1.fill.effect.sigma = 140
drop1:invalidate("canvas")
drop1:scale(0.75, 90)
drop1:invalidate("canvas")
drop1:scale(1, 1 / 60)
drop1:invalidate("canvas")
local drop = display.newSnapshot(drop1.contentWidth * 1.5, drop1.contentHeight)
drop.canvas:insert(drop1)
drop.fill.effect = "filter.blurHorizontal"
drop.fill.effect.blurSize = 10
drop:invalidate("canvas")
drop.alpha = 0.375
local randomY = math.random(-500, 500)
drop.y = randomY
drop.anchorY = 0
drop.x = (i - 1) * 54
drops[i] = drop
table.insert(t.drops, drop)
local dropV, drop1, drop = nil
end
composer.setVariable("drops", t.drops)
t.fall(drops, group)
drops = nil
t.clean()
end
return t
编辑:我发现它肯定与嵌套快照有关,嵌套快照是为应用滤镜效果而创建的。我删除了一个快照,这样我在快照中只有一个矢量对象,瞧:内存增加得更慢。问题是:为什么?
通常,您根本不需要 enterFrame 事件 - 您可以简单地从起点 (math.random(-500, 500)) 过渡到终点(代码中的 2000)。只是随机化速度并使用 onComplete 处理程序来删除对象
local targetY = 2000
local speedPerMs = math.random(32, 64) * 60 / 1000
local timeToTravel = (targetY - randomY) / speedPerMs
transition.to( drop, {
time = timeToTravel,
x = xx,
y = targetY,
onComplete = function()
drop:removeSelf()
end
} )
编辑 1: 我发现用您的代码删除 drop 是不够的。这对我有用:
drop:removeSelf()
dropV:removeSelf()
drop1:removeSelf()
关于内存消耗的一些想法:
1) 或许您可以对滴数组使用 1 个 enterFrame 处理程序 - 这将减少内存消耗。也不要向本地对象添加方法,例如 'function thisDrop:enterFrame()' - 这在这里不是最佳选择,因为您每 50 毫秒
创建 20 个新函数
2) 您的代码每秒创建 400 个 'drop' 对象,它们通常不超过 78 帧(在 60fps 环境中为 1.3 秒)。最好使用对象池并重用现有对象
3) enterFrame 函数取决于设备当前的 fps,因此 fps 低时下雨速度会变慢。低 fps -> 物体下降得更慢 -> 场景中有更多物体 -> fps 下降。我建议你计算 2 次 enterFrame 调用之间的 deltaTime 并根据 deltaTime
调整下降速度
编辑 2 快照的 :removeSelf() 似乎没有删除子对象。我修改了你的代码,内存消耗下降了很多
if self.y > 2000 then
local drop1 = self.group[1]
local dropV = drop1.group[1]
dropV:removeSelf()
drop1:removeSelf()
self:removeSelf()
Runtime:removeEventListener("enterFrame", self)
self = nil
end
所以我有一个正在开发的游戏的 rain 模块,它会导致大量系统内存泄漏,从而导致延迟并最终导致应用程序崩溃。 函数 "t.start" 每 50 毫秒用定时器调用一次。
虽然我试过了,但我真的找不到原因!也许我忽略了一些东西,但我无能为力。如您所见,我删除了与当地人相关的图形...有人注意到什么了吗?
作为次要问题:有没有人有关于预加载下一个场景以平滑场景切换的提示?因为当我把它放在 "scene:show()"...
时,加载本身会导致短暂的冻结感谢您的帮助! 你好,尼尔斯
local t = {}
local composer = require("composer")
t.drops = {}
function t.fall(drops, group)
for i = 1, #drops, 1 do
local thisDrop = drops[i]
function thisDrop:enterFrame()
if aboutToBeDestroyed == true then
Runtime:removeEventListener("enterFrame", self)
return true
end
local randomY = math.random(32, 64)
if self.x ~= nil then
self:translate(0, randomY)
if self.y > 2000 then
self:removeSelf()
Runtime:removeEventListener("enterFrame", self)
self = nil
end
end
end
Runtime:addEventListener("enterFrame", drops[i])
thisDrop = nil
end
end
t.clean = function()
for i = 1, #t.drops, 1 do
if t.drops[i] ~= nil then
table.remove(t.drops, i)
t.drops[i] = nil
end
end
end
function t.start(group)
local drops = {}
local theGroup = group
for i = 1, 20, 1 do
local randomWidth = math.random(5, 30)
local dropV = display.newRect(group, 1, 1, randomWidth, 30)
local drop1 = display.newSnapshot(dropV.contentWidth , dropV.contentHeight * 3)
drop1.canvas:insert(dropV)
drop1.fill.effect = "filter.blurVertical"
drop1.fill.effect.blurSize = 30
drop1.fill.effect.sigma = 140
drop1:invalidate("canvas")
drop1:scale(0.75, 90)
drop1:invalidate("canvas")
drop1:scale(1, 1 / 60)
drop1:invalidate("canvas")
local drop = display.newSnapshot(drop1.contentWidth * 1.5, drop1.contentHeight)
drop.canvas:insert(drop1)
drop.fill.effect = "filter.blurHorizontal"
drop.fill.effect.blurSize = 10
drop:invalidate("canvas")
drop.alpha = 0.375
local randomY = math.random(-500, 500)
drop.y = randomY
drop.anchorY = 0
drop.x = (i - 1) * 54
drops[i] = drop
table.insert(t.drops, drop)
local dropV, drop1, drop = nil
end
composer.setVariable("drops", t.drops)
t.fall(drops, group)
drops = nil
t.clean()
end
return t
编辑:我发现它肯定与嵌套快照有关,嵌套快照是为应用滤镜效果而创建的。我删除了一个快照,这样我在快照中只有一个矢量对象,瞧:内存增加得更慢。问题是:为什么?
通常,您根本不需要 enterFrame 事件 - 您可以简单地从起点 (math.random(-500, 500)) 过渡到终点(代码中的 2000)。只是随机化速度并使用 onComplete 处理程序来删除对象
local targetY = 2000
local speedPerMs = math.random(32, 64) * 60 / 1000
local timeToTravel = (targetY - randomY) / speedPerMs
transition.to( drop, {
time = timeToTravel,
x = xx,
y = targetY,
onComplete = function()
drop:removeSelf()
end
} )
编辑 1: 我发现用您的代码删除 drop 是不够的。这对我有用:
drop:removeSelf()
dropV:removeSelf()
drop1:removeSelf()
关于内存消耗的一些想法:
1) 或许您可以对滴数组使用 1 个 enterFrame 处理程序 - 这将减少内存消耗。也不要向本地对象添加方法,例如 'function thisDrop:enterFrame()' - 这在这里不是最佳选择,因为您每 50 毫秒
创建 20 个新函数2) 您的代码每秒创建 400 个 'drop' 对象,它们通常不超过 78 帧(在 60fps 环境中为 1.3 秒)。最好使用对象池并重用现有对象
3) enterFrame 函数取决于设备当前的 fps,因此 fps 低时下雨速度会变慢。低 fps -> 物体下降得更慢 -> 场景中有更多物体 -> fps 下降。我建议你计算 2 次 enterFrame 调用之间的 deltaTime 并根据 deltaTime
调整下降速度编辑 2 快照的 :removeSelf() 似乎没有删除子对象。我修改了你的代码,内存消耗下降了很多
if self.y > 2000 then
local drop1 = self.group[1]
local dropV = drop1.group[1]
dropV:removeSelf()
drop1:removeSelf()
self:removeSelf()
Runtime:removeEventListener("enterFrame", self)
self = nil
end