解决Unity+XLua内存的一些记录
2024/03
31
09:03
一、跟踪对象引用
Lua中的对象被持有(引用),会导致资源的引用也无法断开,所以需要追踪lua中对象是否存在。
使用lua的weak表,把需要追踪的对象放在weak表中,在指定的时候检查此表中是否存在对象,若未被回收,则说明出现了泄漏。
local _MV = { __mode = "v" }
---@class WeakObjMgr
local _M = {}
_M.__index = _M
---@param obj table|function 要追踪的对象
---@param typeName string 大类名称
---@param objName string 小类名称
function _M:Add(typeName, objName, obj)
local objType = type(obj)
if objType ~= "function" and objType ~= "table" then
return false
end
local pool = self.list[typeName]
if pool == nil then
pool = {}
self.list[typeName] = pool
end
table.insert(pool, setmetatable({ objName, obj }, _MV))
return true
end
--- 汇报
function _M:Report()
collectgarbage("collect")
local tips = {}
for typeName, pool in pairs(self.list) do
local len = #pool
for i = len, 1, -1 do
if pool[i][2] == nil then
table.remove(pool, i)
else
table.insert(tips, typeName .. ":" .. tostring(pool[i][1]))
end
end
end
return table.concat(tips, "\n")
end
---@type WeakObjMgr
WeakObjMgrIns = setmetatable({ list = {} }, _M)
--- 使用的时候WeakObjMgrIns:Add("mainCity", "avatar", avatarObj)
二、在XLua中添加新增userdata的追踪
public partial class ObjectPool
{
public int GetCount()
{
int c = 0;
for(int i=0; i<list.Length; ++i)
{
if (list[i].obj != null)
{
++c;
}
}
return c;
}
private HashSet<int> mSaveSnap = new HashSet<int>();
public void SaveSnap()
{
for(int i=0; i<list.Length; ++i)
{
var obj = list[i].obj;
if (obj != null)
{
mSaveSnap.Add(obj.GetHashCode());
}
}
}
private static string GetObjName(object obj)
{
try
{
if (obj is UnityEngine.GameObject)
{
return (obj as UnityEngine.GameObject).name;
}
...其它的一些对象名称
}
catch(Exception)
{
}
return string.Empty;
}
// 对比出增量
public string Compare()
{
HashSet<int> current = new HashSet<int>();
for(int i=0; i<list.Length; ++i)
{
var obj = list[i].obj;
if (obj != null)
{
current.Add(obj.GetHashCode());
}
}
List<(string typeName, string objName, int n)> ls = new List<(string typeName, string objName, int)>();
foreach(var id in current)
{
if (mSaveSnap.Contains(id))
{
continue;
}
if (ObjectPool.mAllObjs.TryGetValue(id, out var info))
{
ls.Add((info.tyepName, info.objName, 1));
}
}
ls.Sort( (a,b)=>
{
if (a.typeName == b.typeName)
{
return a.objName.CompareTo(b.objName);
}
return a.typeName.CompareTo(b.typeName);
});
int count = ls.Count;
for(int i=count-1; i>0; --i)
{
if (ls[i].typeName == ls[i-1].typeName && ls[i].objName == ls[i-1].objName)
{
ls.RemoveAt(i);
ls[i-1] = (ls[i-1].typeName, ls[i-1].objName, ls[i-1].n+1);
}
}
StringBuilder sb = new StringBuilder();
foreach(var s in ls)
{
if (s.n > 1)
sb.AppendLine($"{s.typeName} [{s.n}] : {s.objName}");
else
sb.AppendLine($"{s.typeName} : {s.objName}");
}
return sb.ToString();
}
public static Dictionary<int, (string tyepName, string objName)> mAllObjs = new Dictionary<int, (string, string)>();
public void PostAdd(object obj)
{
if (obj == null)
{
return;
}
var typeName = obj.GetType().Name;
var objName = GetObjName(obj);
var hashCode = obj.GetHashCode();
mAllObjs[hashCode] = (typeName, objName);
}
}
然后定时进行Compare
三、XLua送的LuaMemoryLeakChecker
不太好用,输出出来的对象比较混乱
未完待续
CopyRights: The Post by BY-NC-SA For Authorization,Original If Not Noted,Reprint Please Indicate From 老刘@开发笔记
Post Link: 解决Unity+XLua内存的一些记录
Post Link: 解决Unity+XLua内存的一些记录