본문 바로가기
Engine/Unity3D

유니티 Memory leak을 잡아보자!

by 황금표정 2016. 12. 27.

많은 유니티 개발자들이 고민하는 부분이 아마 "메모리 누수"일텐데


저도 메모리 누수 때문에 고민을 많이 하고 있습니다.


보통 게임 개발을 하다보면 싱글톤 패턴을 사용하게 될 수 밖에 없는 상황이 오는데요


애초에 이런 문제를 피하기 위해서 싱글톤을 사용하지 않고 DontDestroyOnLoad() 함수를 사용해서 


씬이 전환 될 때의 객체파괴를 막고 사용하는 방법도 있습니다!


물론 이런건 전부 개발 스타일과 게임의 스타일 그리고 상황에 맞춰서! 사용하시면 됩니다.



이 글을 쓰는 이유는...


최근에 진행중인 프로젝트에 메모리 누수 관련 이슈가 들어와서 살펴보고 있습니다 (ㅠㅠ엉엉)


일단 보통 많이들 문제가 되는 부분이 reference를 참조하고 그 참조를 해제하지 않는 경우가 가장 문제가 됩니다.


유니티에서는 Reference Count 방식으로 리소스를 관리하고 있습니다. 해당 오브젝트를 참조할 때 마다 Reference Count를 증가시키고


참조했던 오브젝트가 참조를 해제하면 해당 리소스의 Reference Count를 감소시키고 감소시킨 Reference Count가 0이 되고


Resources.UnloadUnusedAssets(); 함수가 호출 되었을 때 Reference Count가 0인 오브젝트를 메모리에서 해제 시키게 됩니다.


(C#은 메모리 알아서 관리해준다던데?) 에 속아서 이런 일이 발생하지 않도록 합시다.



간단한 샘플코드로 이해를 도와드리겠습니다~


코드는 이렇구요




실행!!





저렇게 프로파일링을 해보면 메모리가 Assets에 메모리가 남아있게 되는 것을 확인 할 수 있습니다.


보통 여기서 추가적으로 더 처리한다면 OnDestroy() 함수에서 null처리를 추가하는 경우가 있습니다.






결과를 한번 볼까요?





null을 처리해도 여전히 메모리에 잡히는군요!?


분명 null을 대입함으로써 Reference Count를 감소시켰을텐데 왜그럴까요?


이유는 해제에 대한 콜을 해주어야 합니다.


바로 위에서 말씀드렸던


Resources.UnloadUnusedAssets(); 함수입니다.


해당 함수의 설명은 이렇게 되어있습니다.


"Unloads assets that are not used."

사용하지 않는 assets를 Unload시킨다입니다.


한번 해당 함수를 호출해서 확인해보도록합시다.


코드는 이렇게






결과는???!!






메모리상에서 잡히지 않는 것을 확인했습니다!





추가적으로 말씀드리자면, OnDestroy() 함수에서 m_Image = null; 을 주석처리해도 메모리는 해제가 됩니다.

왜냐하면 MemoryTest 스크립트와 Image가 같은 오브젝트에 있기때문입니다.





AutoDestroy() 코루틴에서 gameObject 자체를 지우면서 MemoryTest에서 m_Image에 대한 참조를 끊어주기 때문에 Reference Count가

없어지기 때문입니다.


gameObject대신에 m_Image를 Destroy처리 해보시면 결과가 다르게 나올 것 입니다.



해당 결과는 아래와 같이 나오게 되며, 궁금하시면 직접 테스트해보시길 권장합니다!^^









결론.

Reference Count 관리 잘 부탁드립니다. ( _ _ )

반응형