Closed AlanLiu90 closed 2 years ago
看代码的时候,发现 MachineState 没有地方释放,并且析构函数中 _frameBase 和 _exceptionFlowBase 也没有释放。 用 Unity 2020.3.33+Win64,运行下面的代码,内存会不断增长:
void Start() { StartCoroutine(Test()); } IEnumerator Test() { Thread[] threads = new Thread[4]; while (true) { for (int i = 0; i < threads.Length; ++i) { Thread t = new Thread(Run); threads[i] = t; t.Start(); } for (int i = 0; i < threads.Length; ++i) { threads[i].Join(); threads[i] = null; } yield return new WaitForSeconds(5); } } void Run() { Thread.Sleep(1); }
我自己尝试改了下代码验证,发现确实是 MachineState 没释放导致的:
--- a/hybridclr/interpreter/Engine.h +++ b/hybridclr/interpreter/Engine.h @@ -56,6 +56,8 @@ namespace interpreter ~MachineState() { + IL2CPP_FREE(_exceptionFlowBase); + IL2CPP_FREE(_frameBase); il2cpp::gc::GarbageCollector::FreeFixed(_stackBase); } --- a/hybridclr/interpreter/InterpreterModule.h +++ b/hybridclr/interpreter/InterpreterModule.h @@ -19,6 +19,7 @@ namespace interpreter static MachineState& GetCurrentThreadMachineState(); + static void ClearCurrentThreadMachineState(); static InterpMethodInfo* GetInterpMethodInfo(const MethodInfo* methodInfo); --- a/hybridclr/interpreter/InterpreterModule.cpp +++ b/hybridclr/interpreter/InterpreterModule.cpp @@ -38,6 +38,18 @@ namespace hybridclr return *state; } + void InterpreterModule::ClearCurrentThreadMachineState() + { + MachineState* state = nullptr; + s_machineState.GetValue((void**)&state); + + if (state) + { + s_machineState.SetValue(nullptr); + delete state; + } + } + void InterpreterModule::Initialize() { for (size_t i = 0; ; i++)
--- a/libil2cpp/vm/Thread.cpp +++ b/libil2cpp/vm/Thread.cpp @@ -29,6 +29,8 @@ #include "Cpp/Atomic.h" #include "Cpp/ReentrantLock.h" +#include "hybridclr/interpreter/InterpreterModule.h" + #if IL2CPP_MONO_DEBUGGER extern "C" { @@ -355,6 +357,8 @@ namespace vm Uninitialize(thread); il2cpp::vm::StackTrace::CleanupStackTracesForCurrentThread(); + + hybridclr::interpreter::InterpreterModule::ClearCurrentThreadMachineState(); } Il2CppThread* Thread::Main() @@ -730,6 +734,8 @@ namespace vm il2cpp::vm::Thread::Uninitialize(startData->m_Thread); il2cpp::vm::StackTrace::CleanupStackTracesForCurrentThread(); + + hybridclr::interpreter::InterpreterModule::ClearCurrentThreadMachineState(); } delete startData->m_Semaphore; --- a/libil2cpp/icalls/mscorlib/System.Threading/Thread.cpp +++ b/libil2cpp/icalls/mscorlib/System.Threading/Thread.cpp @@ -20,6 +20,8 @@ #include "utils/Memory.h" #include "utils/StringUtils.h" +#include "hybridclr/interpreter/InterpreterModule.h" + using il2cpp::gc::GarbageCollector; namespace il2cpp @@ -169,6 +171,8 @@ namespace Threading il2cpp::vm::Thread::Uninitialize(startData->m_Thread); il2cpp::vm::StackTrace::CleanupStackTracesForCurrentThread(); + + hybridclr::interpreter::InterpreterModule::ClearCurrentThreadMachineState(); } delete startData->m_Semaphore;
感谢。这个问题是已知的,因为觉得客户端没人会不停地创建线程。我们考虑某个时候修复它。
我们游戏刚好是会受这个问题影响的:游戏是区分大厅和战斗场景的,每次开启新的一局游戏(进入战斗场景),导航系统(不是Unity的,是我们自己实现的)就会创建几个线程,离开战斗场景时,这些线程会随着导航系统销毁而销毁。
官方修复这个问题前,我们先自己解决。
我们现在就修复它
这个问题已经修复提交
看代码的时候,发现 MachineState 没有地方释放,并且析构函数中 _frameBase 和 _exceptionFlowBase 也没有释放。 用 Unity 2020.3.33+Win64,运行下面的代码,内存会不断增长:
我自己尝试改了下代码验证,发现确实是 MachineState 没释放导致的: