Unity 应用程序内存泄漏 - 如何在不访问源代码或调试目标的情况下进行分析?

Unity Application Memory Leak - How can you profile without access to the source code or a debug target?

提问人:ThompsonCodes 提问时间:2/28/2023 更新时间:3/1/2023 访问量:566

问:

这里有点不寻常的设置,

  • 我正在为视频游戏 RUST 创建模组
  • 它使用 HARMONY 将 mod 加载到服务器代码中
  • 在某些时候,我做了一些导致内存泄漏的事情,该应用程序在一天内从 10GB 内存增长到 30GB,有数百名玩家使用它。
  • 这些模组是用C#编写的,但Unity的核心是C++
  • 卸载所有 mod 不会导致 GC 清理已使用的内存,即使在手动调用 gc.collect 时也是如此。

我尝试过连接传统的内存分析器,如 ANTS 和 dotMemory,但它们没有连接——我敢肯定这与没有发布版本或它是 Unity 应用程序的事实有关。

我尝试连接Unity调试器,但它无法识别游戏。

我没有选择,有谁知道是否可以要求 GC 转储当前正在跟踪的对象?也许可以使用 Harmony 挂钩到 GC 中实际分配的内存步骤,我可以手动跟踪?

C# Unity-game-engine 内存泄漏分析 和谐

评论


答:

0赞 NPatch 2/28/2023 #1

Unity 有多个后端。它有 Mono 一个是 C#,它有一个 IL2CPP 一个是 C++。此外,无法分析基于 Unity 的发布版本 afaiu。

既然我们谈论的是模组,也许可以做一些测试,看看它是你的模组,还是其他加载的模组,或者它是否发生在你加载了多个或特定的模组时,甚至是它们自己等。

评论

0赞 ThompsonCodes 3/1/2023
我可以确认内存堆积在单声道方面。这几乎可以肯定是由于模组,但它是这个整体的野兽,禁用模组是不可能的——这是一个完整的转换游戏模式。我仍然对我可以与 Harmony 挂钩的东西抱有希望,以跟踪活跃的参考。我也可以说,这并不是一大堆游戏对象堆积起来——至少在场景中是这样。打印出游戏对象相对容易。
0赞 NPatch 3/1/2023
我只记得,如果 mod 是常规的 C# 程序集,那么也许您可以使用 dnSpy 修改它们并添加某种形式的跟踪。假设您无权访问 mod 源代码。
0赞 ThompsonCodes 3/2/2023
我可以访问 mod 源代码——如果有某种方法可以让那个东西打印出所有引用和它使用的内存,那将是一个开始!我使用 dnSpy 读取原始游戏的源代码,但我不确定如何应用它来追踪我的 mod 造成的内存泄漏。
0赞 NPatch 3/2/2023
我会试试苏尼乌斯的建议。Profiler 可以显示一些每帧分配,因此您可以在那里过滤一些数据,或者使用 MemoryProfiler 并查看快照的差异。两个分析器都可以附加到玩家身上(尽管 MemProf 只在开发/调试版本上,但 Sunius 的建议可能有效)。
2赞 Sunius 3/1/2023 #2

如果您下载的Unity版本与制作游戏的版本完全相同(您可以在UnityPlayer.dll的属性页面中查看它是什么),则可以将UnityPlayer.dll从开发版本交换到游戏中,然后使用Unity的内存分析工具。也就是说,这只有在游戏使用相对较新的Unity版本(在过去3-5年内制作)时才有效。

评论

0赞 ThompsonCodes 3/2/2023
感谢您的宝贵建议!如果项目是用调试版本导出的,任何 UnityPlayer.dll 都可以工作吗?我无法访问游戏本身的开发版本 - UnityPlayer.dll 与单个游戏代码完全分开吗?
0赞 Sunius 3/2/2023
UnityPlayer.dll 对于在 Unity 中制作的所有游戏都是相同的,给定特定版本的引擎。它与引擎一起预编译,游戏开发人员无法修改它。
0赞 ThompsonCodes 3/13/2023
这奏效了,它允许我使用内存分析器来调试游戏。非常感谢大家!