본문 바로가기
Dev/고민과 삽질의 기록들🤔

[iOS] 메모리 뜯어보기 (힙할당 줄이기 및 누수 해결하기)

by Mintta 2023. 3. 11.

WWDC의 메모리 디버깅을 보고 문득 호기심이 생겨서 프로젝트에서 구현했던 메인홈에서의 메모리가 궁금했습니다. 궁금했던 이유는 거기에 Airbnb에서 만든 라이브러리인 lottie-ios의 라이브러리의 기능 AnimationView를 이용한 무한재생 로티가 있고(얘가 얼마나 메모리를 잡아먹을지), 여러가지 정보가 종합해서 보여지는 메인홈이였기에 한번 메모리를 Instruments로 찍어보고 싶었습니다. 그리고 내가 직접 구현한 화면이니까 그냥 궁금했던 점이 컸습니다ㅎ

 

한번 살펴볼까요??🚀🚀🚀

 

어라?? 근데 이게 뭐지🤔

  • 4분 2초간 profile

아래 칸에 첫번째, 두번째줄을 보시면 빨간색 overhead가 잔뜩 표시되고, 힙 할당이 로티가 반복재생되는 순간을 기점으로 계속 증가하고 있었습니다

위의 사진은 4분 2초동안 profile중이였는데 이 때를 기준으로 10,854,470의 힙할당이 있네요..!

  • 6분 4초간

약 2분이 지난 후 현재 16,396,866의 힙할당이 이뤄지고 있습니다…

 

이게 뭐지?????????🤮🤮

저번에 WWDC세션을 듣고 분명히 힙할당을 줄이고자 그렇게나 값타입에 대한 설명을 했는데 로티가 힙할당을 무한정 증가시키고 있었습니다….!!

 

일단 놀란 마음을 진정시키고 lottie 깃허브에 들어가서 memory를 키워드로 검색해봅니다..

 

역시! 제가 생각한 문제가 저한테만 있는건 아니였나봅니다

이와 같은 이슈를 겪는 사람들이 매우 많았고 마지막에 이 대화는 마지막에 calda가 만든 새로운 rendering engine이 더욱 나은 성능을 가지고 있고 해당 엔진을 configuration으로 넣어보기를 권장하고 있었다 !

(쭉 읽어보긴 했는데…사실 얘기하는 걸 온전히 이해하지 못했다ㅜㅜ)

 

그렇다면 한번 새로운 엔진으로 config해서 AnimationView를 만들어보러가보자 !

 

  • 21분 가량

계속 켜두면 어떤일이 일어나는지 보고싶어서 켜두었는데 이제 보내줄게…

 

이제 설정을 바꿔보자 !

private var dailyLottie = AnimationView(configuration: .init(renderingEngine: .coreAnimation))

 

이제 다시 메모리를 살펴봐야겠다..!

  • 40초쯤 지난 기준으로 힙할당 22,925이 찍혀있다

 

  • 4분이 지난 후에도 49,655 !

아까 위에서의 4분 때에는 10,854,470의 힙할당이 일어났던거에 비해 현저히 낮은 수임과 동시에 증가한 수도 많지 않다!!

 

근데 저 아래 Leaks에 불길한 빨간표시는 뭘까..?? 이럴수가 메모리 누수라니..

다시 Instrument를 켜보자 !

  • UITapGestureRecognizer
  • UITapRecognizer

요두놈이 범인들인가봅니다..이제 backtrace를 해볼까요??

 

방법은 첫번째 Instruments에 제공하는 Back trace인데 요곤 제가 restart를 해서 처음부터 추적하지 않으면 (뒤늦게 눌렀거나) 하면 추적이 안되더라고요

저는 Memgraph파일을 Xcode에서 export한 뒤 터미널에서 malloc_history를 통해서 back trace해보았습니다 !

으아ㅏㅏㅏ(이거 가독성 좋게 나오는 법 아시나요??ㅠㅠ)

일단 한번 살펴봅시다. 일단 제 눈에 들어오는 익숙한 암수가 저 아래에 깔려있네요

  • UITapGestureRecognizer.__allocating_init()
  • MainHomeViewController.configureCollectionViewCell(collectionView:indexPath:item:)
  • #2 in MainHomeViewController.bind()
  • CollectionViewSectionedDataSource.collectionView(_:cellForItemAt:)

오호…그니까 CollectionView에서 cellForItemAt함수에 cell을 설정해주는 함수에 제가 무언가 실수를 했나보군요..

configureCollectionViewCell 메서드에서 UITapGestureRecognizer를 생성하는 부분이 어떤게 있는지 한번 찾아봐야겠군요… 소스 코드 보러 가봅시다

 

찾았다 !

view에 대한 입력을 편하게 하기위해서 RxGesture를 쓰고 있었는데 tap을 driver로 바꾸는 과정에서 저 생성자로 빠지면서 에러를 일으키는 듯합니다..!

 

보아하니 Subject에 신호를 전달해줄뿐 딱히 UI관련된 메인스레드가 필요한 일을 하는게 아니였기에 subscribe로 해줘도 무방할 듯 해보입니다!

한번 수정해보겠습니다

 

이제 다시 프로파일 해봅시다 !

메모리 누수가 없어졌습니다..! 해치웠다✨

 

 

+추가로 Instrument에 뜨는 back trace에는 이렇게 생겼습니다 !

확실히 터미널보다 보기는 훨씬 깔끔하고 편하네요 !

 

 

처음 메모리를 열어서 개선이라 할 수 있을만한지는 모르겠지만 나름 힙할당도 줄여보고 누수도 직접 해결해보았습니다 !

직접 이렇게 메모리를 열어서 back trace도 해보니 괜한 겁을 먹고 있었다는 생각이 드네요 역시 처음의 경험이 무조건 중요한 것 같습니다

메모리 누수나 메모리 관련해서는 코딩하면서도 신경쓰면서 해야겠지만, 언제나 실수는 있을 수 있고 누수는 예기치 못한 곳한 곳에서 나오므로 메모리 디버깅도 습관화해서 적극적으로 해야겠습니다. 추가적으로 남는 의문점들을 남기고 저는 천천히 고민해봐야겠네요

혹시나 누군가에게 제 디버깅 경험이 도움이 되면 좋겠습니다 !

 

고민해봐야할 의문점❓

  • lottie-ios에서 coreAnimation을 렌더링 엔진을 하고 안하고 어떤 차이가 있길래 이렇게 힙 할당이 크게 차이가 나는 것일까??
  • Driver에서 errorjustreturn으로 빠졌을 때 UITapGestureRecognizer init된게 어째서 누수가 되는 것일까?

 


Uploaded by

N2T

댓글