memory leak은 성능 저하의 원인중 하나이고, 최적화를 위해 잡아야 하는 문제들중 하나이다.
unity 내부에서 memoty leak을 유발 할 수 있는 이슈중 하나로, 잔류 unity instance가 있다. 이 경우 어디서 어떤 오브젝트가 누수가 되고 있는 지 확인하기가 어렵다. 이현상에 대해서 잠깐 짚고 넘어가보자.
실제로 Unity Engine은 C#의 Managed shell과 C++로 이루어진 Native 엔진 코드로 이루어져 있다. C#에 할당된 오브젝트를 Wrapper object, C++에 할당된 오브젝트를 Native Object라고 부르겠다. 잠깐 설명하고 넘어가자면, 실질적인 오브젝트는 Native Object로 실직적인 process는 여기에 존재한다. Wrapper obect는 이 native object에 대한 pointer이다.
일반적인 경우, Wrapper object는 GC에서 레퍼런스가 존재하지 않는 힙영역을 회수 하면서 관리가 되고, C++ Native object는 씬 전환 혹은 manual로 메모리 해제(Destroy(); 같은)를 해주어 관리한다. 하지만, 내가 오브젝트를 Destroy() 하고 그오브젝트를 C#에서 호출하면 null이 나오게 된다. 실질적으로 GC에서 힙할당을 해제하기도 전에 말이다.
이게 어떻게 가능한 것인가. 유니티 object클래스를 보면 custom operator == 가 overloaing 되어 있는 것을 확인 할수가 있다. 그래서, 실질적인 Wrapper object가 null이 아니더라도, fake null object를 비교하여 null로서 보이게 되는 것이다.
이 고질적인 문제에 대해서는 예전부터 이야기가 있었다. 자세한 것은 유니티 공식 블로그를 보자.
https://blog.unity.com/engine-platform/custom-operator-should-we-keep-it
그렇다면, 저 wrapper object가 누수 되지 않게 되려면, 직접 tex =null; 이런식으로 null처리를 해주어야 한다.
근데 문제가 있다. 이를 찾기가 너무 어렵다는 것이다.
기존의 profiler를 통해서는 이 memory leak이 어디서 발생하는 지 알기 어려웠다. 하지만, Memory Profiler라는 강력한 툴을 유니티에서 제공함으로서, 발생 근원지와 두 시점의 메모리 사용 차이를 보여줌으로서, 메모리 최적화에 큰 도움을 주고 있다. (leaked를 처보면 wrapper object(managed shell은 c#영역을 의미)가 남아있는 것을 확인할수가 있다.)
22년 이후 버전에서만 사용이 가능하고, 아직 실험 단계 이기 때문에 일반적인 profiler와 달리 아직 패키지 매니저를 통해서 따로 다운 받아줘야 하며, experimental이라는 딱지가 아직 붙어있다.
스냅샷을 찍어서 목록으로 저장하고, 이들을 비교할수가 있다.
이러한, 메모리 프로파일러의 사용법은 밑의 유니티 공식 블로그에서 확인할수가 있다.
https://blog.unity.com/kr/engine-platform/everything-you-need-to-know-about-memory-profiler
'Game Dev > Unity' 카테고리의 다른 글
개인 프로젝트 - 터치 크래프트 (1) (0) | 2024.01.20 |
---|---|
Unity Ecs란 무엇일까 (1) | 2023.12.30 |
유니티 네트워킹 - NetworkVariable vs RPC (0) | 2023.10.14 |
유니티 Field of View 구현 - 폴리곤 Mesh (0) | 2023.09.16 |
유니티 - 멀티플레이어 게임 Lock Step 동기화 (0) | 2023.08.20 |