본문 바로가기

ANDROID

[안드로이드] handler의 static final화를 통한 메모리 Leak 해결

앱 테스트 중 메모리 leak으로 인해 메모리 allocation이 지속적으로 쌓이고, 결과적으로


앱 실행속도가 점진적으로 크게 느려지는 현상이 계속되고 있었다.


원인을 파악하고자 안드로이드 스튜디오의 android profiler를 실행해두고 테스트를 약 10분에서 20분 가량 진행했다.


테스트를 진행하면서 종류별 메모리 사용량을 체크하였고, 고정된 구간과 주로 적체되는 구간들을


체크하였고 테스트 이후 메모리 덤프로 할당된 메모리의 상세 내용을 체크해보았다.


체크 결과 생각보다 상세하게 주로 적체된 메모리의 상세 내용을 찾아볼 수 있었다.



문제는 특정 액티비티가 진작에 종료되고 사라졌어야 하는 시점에 사라지지 않고 테스트를 수행한 횟수만큼 딱 쌓여있다는 것이었다.


이와 관련된 다른 메모리들을 참조해보았고 결과적으로 handler와 연관된 요소들이 주로 함께 적체되어왔음을 확인할 수 있었다.


기존의 코드에서는 thread에서 while(true)라는 단순한 조건으로 수행되고 있는 조건이 있었음은 물론 


handler가 아닌 thread에서 view를 건드리는 부분도 존재하고 있었고(thread에서 handler로 메시지를 보내는 부분이 있다)


기존의 핸들러의 leak 경고를 단순히 Annotation을 추가해 disable해주고 있었음을 확인했다.


이에 서치를 통해 handler leak이 안드로이드에 대중적으로 퍼져있는 문제였음을 보았고,


해결책으로 handler를 static final로 선언해 기능을 수행하는 것으로 memory leak을 방지할 수 있다는 내용이었다.


선언부분은 조금 복잡한 면이 있지만, 기존에 쓰던 handlerMessage 함수를 그대로 이용할 수 있기 때문에


초반 코드만 잘 적용할 수 있다면 handler로 인한 memory leak은 걱정할 일이 없을 것이다 :)



아래는 handler를 모두 static final로 선언해 준 다음의 메모리 모니터링 결과다. 


메모리 사용량이 많은 그래픽 구현 부분을 뒤로 쌓이는 일 없이 안정화된 모습을 확인해 볼 수 있다.



수치로 확인해봤을 때, 기존에 10000개에서 15000개까지 쌓이던 memory alloc이 코드 수정 이후


10000개 위아래를 유지하는 아주 가시적인 결과를 가져오는 걸 볼 수 있었다.


앱을 실제로 사용하는 중에서도 이전만큼 앱이 느려지는 현상은 사라졌음을 확인할 수 있었다.



<수정 이전 >



<수정 이후> 


( 수정 이전 스크린샷은 측정수치를 적지 않으면서 진행했기 때문에 대기하는 텀이 없어 이후 그래프와 확연히 달라보이는 점이 있다.


우측 상단에 표시된 메모리 관련 데이터만 참조하면 보다 객관적으로 이전 이후를 비교해볼 수 있겠다.)



메모리 leak 및 성능향상을 위해 android profiler를 계속 참조하게 되면서, 어느정도 할당된 메모리와 적체된 메모리, 사용되는 구간등을


확인해보는데 어느정도 능숙해졌다는 기분이 든다. 이번에는 큰 문제이긴 했던 memory leak을 해결하긴 했지만, 


전체적인 성능향상을 가져올 수 있는 변수 설정도 앞으로 유사한 실험 및 과정을 통해 해결해나갈 수 있을 것이라 기대한다 :)


향후 변수 설정등을 통한 성능 최적화는 서치중에 발견한 아래 포스트를 보고 해 나갈 생각이다. 구체적이고 종합적으로


앱 성능에 영향을 미치는 요소들에 대해 설명해주고 있는 포스트이다.


https://android.jlelse.eu/android-performance-patterns-rescue-tips-8c1e4c7cb1f0



참고 :


http://regularmotion.kr/android-how-to-leak-a-context-handlers-inner-classes/


http://mainia.tistory.com/1393