117 lines
3.7 KiB
Lua
117 lines
3.7 KiB
Lua
|
||
|
||
LuaObjectMemoryLeakChecker = HL.Class('LuaObjectMemoryLeakChecker')
|
||
|
||
local GCMeta = {}
|
||
|
||
LuaObjectMemoryLeakChecker.destoryObjects = HL.Field(HL.Table)
|
||
|
||
LuaObjectMemoryLeakChecker.isGcEnd = HL.Field(HL.Boolean) << false
|
||
|
||
LuaObjectMemoryLeakChecker.coCheker = HL.Field(HL.Thread)
|
||
|
||
LuaObjectMemoryLeakChecker.LuaObjectMemoryLeakChecker = HL.Constructor() << function(self)
|
||
self.destoryObjects = {}
|
||
setmetatable(self.destoryObjects, {__mode = "k"})
|
||
end
|
||
|
||
|
||
LuaObjectMemoryLeakChecker.checkRegisterGC = HL.Method() << function(self)
|
||
while true do
|
||
coroutine.wait(2,self.coCheker)
|
||
if self.isGcEnd then
|
||
self:_DetectLuaObject()
|
||
self:_ReStartChecker()
|
||
end
|
||
end
|
||
end
|
||
|
||
LuaObjectMemoryLeakChecker._ReStartChecker = HL.Method()<< function(self)
|
||
if self.coCheker then
|
||
CoroutineManager:ClearCoroutine(self.coCheker)
|
||
self.coCheker = nil
|
||
end
|
||
self:_createGCListenerTable()
|
||
end
|
||
|
||
LuaObjectMemoryLeakChecker._createGCListenerTable = HL.Method()<< function(self)
|
||
if self.coCheker ~= nil then
|
||
return
|
||
end
|
||
|
||
local coCheker = CoroutineManager:StartCoroutine(function()
|
||
LuaObjectMemoryLeakChecker.checkRegisterGC(self)
|
||
end)
|
||
|
||
local instance = {}
|
||
self.isGcEnd = false
|
||
GCMeta.__gc = function()
|
||
if(coCheker == self.coCheker) then
|
||
self.isGcEnd = true
|
||
end
|
||
end
|
||
setmetatable(instance,GCMeta)
|
||
self.coCheker = coCheker
|
||
end
|
||
|
||
LuaObjectMemoryLeakChecker.AddDetectLuaObject = HL.Method(HL.Any) << function(self, object)
|
||
local GetUserdataAddr = nil
|
||
local address = GetUserdataAddr ~= nil and tostring(GetUserdataAddr(object)) or tostring(object)
|
||
local typeinfo = type(object) == "userdata" and HyperLua.GetTypeName(object) or type(object)
|
||
local time = DateTimeUtils.GetCurrentTimestampByMilliseconds()
|
||
local info = "memory leak address:"..address.." type :"..typeinfo.." start time: "..time
|
||
self.destoryObjects[object] =
|
||
{
|
||
[1] = time,
|
||
[2] = info,
|
||
[3] = address
|
||
}
|
||
self:_ReStartChecker()
|
||
end
|
||
|
||
LuaObjectMemoryLeakChecker.RemoveDetectLuaObject = HL.Method(HL.Any) << function(self, obj)
|
||
self.destoryObjects[obj] = nil
|
||
end
|
||
|
||
|
||
LuaObjectMemoryLeakChecker._DetectLuaObject = HL.Method() << function(self)
|
||
local curTime = DateTimeUtils.GetCurrentTimestampByMilliseconds()
|
||
logger.warn("LuaObjectMemoryLeakChecker finish")
|
||
for object, infos in pairs(self.destoryObjects) do
|
||
if object ~= nil then
|
||
local time = curTime - infos[1]
|
||
logger.error(ELogChannel.UI, infos[2].." duration time:"..time)
|
||
local mri = require ("Debug/MemoryReferenceInfo")
|
||
|
||
mri.m_cConfig.m_bAllMemoryRefFileAddTime = false
|
||
mri.m_cConfig.m_bSingleMemoryRefFileAddTime = false
|
||
mri.m_cConfig.m_bComparedMemoryRefFileAddTime = false
|
||
end
|
||
end
|
||
end
|
||
|
||
|
||
LuaObjectMemoryLeakChecker.DumpAllLeakObject = HL.Method() << function(self)
|
||
collectgarbage("collect")
|
||
collectgarbage("collect")
|
||
local curTime = DateTimeUtils.GetCurrentTimestampByMilliseconds()
|
||
local fireName = CS.Beyond.VFS.UnityFileLoaderHelper.persistentDataPath.."/".."lua_memory_leak_dump_file_"..curTime..".txt"
|
||
logger.error(ELogChannel.UI, "dump lua file "..fireName)
|
||
local mri = require ("Debug/MemoryReferenceInfo")
|
||
mri.m_cConfig.m_bAllMemoryRefFileAddTime = false
|
||
mri.m_cConfig.m_bSingleMemoryRefFileAddTime = false
|
||
mri.m_cConfig.m_bComparedMemoryRefFileAddTime = false
|
||
for object, infos in pairs(self.destoryObjects) do
|
||
if object ~= nil then
|
||
mri.m_cMethods.DumpMemorySnapshotSingleObject(fireName,"", -1, infos[3], object)
|
||
end
|
||
end
|
||
end
|
||
|
||
|
||
HL.Commit(LuaObjectMemoryLeakChecker)
|
||
return LuaObjectMemoryLeakChecker
|
||
|
||
|
||
|