[WWDC18] iOS Memory Deep Dive 2
안녕하세요. 일욜 괴물 소깡입니다. :)
오늘은 지난주에 이어서 iOS Memory에 관한 이야기를 해보려고 합니다. 지난주에 iOS Memory의 Footprint에 대해서 알아보았는데요, 오늘은 메모리를 프로파일링 할 수 있는 툴에 대해서 알아보도록 하겠습니다.
Xcode memory gauge
먼저 Xcode를 통해 확인할 수 있습니다.
Xcode 메모리 게이지는 디버그 네비게이터에 바로 표시됩니다. 이 도구를 사용하면 앱의 메모리 사용량을 빠르게 확인할 수 있습니다.
하지만 해당 세션 설명에 따르면 위 방법(Xcode에서 앱을 실행하여 메모리를 확인하는 방법)은 더 많은 메모리를 소비하여 정확한 측정이 어렵습니다.
Instruments
다음으로 접근할 수 있는 도구는 바로 Instruments 입니다. 이 도구는 앱의 footprint를 조사하는 여러 가지 방법을 제공합니다.
Instruments에서는 위와 같은 내용을 확인할 수 있는데
- Allocations은 Heap 할당을 프로파일링하고
- Leaks는 시간에 따른 메모리 누수를 확인합니다.
이렇게 두 가지는 많이 사용하고 익숙한 방법이지만 그 아래의 VM Tracker, Virtual Memory Trace는 생소할 수 있습니다.
앞서 글에서 (지난 주글에서) iOS의 기본 메모리 클래스를 말했을 때 dirty 메모리와 compressed 메모리에 대해서 말했습니다. VM Tracker는 이를 프로파일링 하는 방법입니다.
iOS에서는 dirty memory와 compressed memory를 나타내는 별도의 트랙이 있으며 이 크기(resident size)에 대한 정보를 제공합니다. 그리고 이것을 이용하여 앱의 dirty memory 크기를 조사할 수 있습니다.
마지막으로 Instruments에는 VM Memory Tracker도 있습니다. 앱과 관련하여 가상 메모리 시스템 성능에 대한 심층적인 정보를 제공합니다.
이 때 By Operation 탭을 이용하여 가상 메모리 시스템 프로필을 제공하며 page cache hits와 page zero fills와 같은 정보를 확인할 수 있습니다.
Page Cache Hit
- 요청된 페이지가 캐시에 이미 존재하여 디스크에서 읽지 않아도 되는 횟수를 의미
- 수치가 높을 수록 디스크 I/O가 줄어들기 때문에 좋습니다.
Zero Fill
- 새로 할당된 페이지의 내용을 모두 0으로 채우는 작업을 의미
- 수치가 낮을 수록 좋습니다. (새로운 메모리를 할당하고 초기화하는데 필요한 비용이 낮다는 것을 의미하므로)
Copy On Write
- 여러 프로세스가 동일한 메모리 페이지를 공유할 때 하나의 프로세스에서 해당 페이지를 수정하면 그 페이지를 다른 프로세스와 별도의 복사본으로 만드는 작업을 의미
- 메모리 공유를 통해 성능을 향상시키며, 동시에 메모리의 효율성을 유지
앞선 내용에서 기기의 메모리 한계에 접근하면 EXC 리소스 예외가 나타난다고 언급했습니다. Xcode10에서 앱을 실행하고 있다면 Xcode가 이 예외를 잡아 앱을 중지하게 됩니다.
이것은 메모리 디버거를 시작하고 여기서부터 조사를 할 수 있다는 것을 의미합니다. Xcode 메모리 디버거는 Xcode8에서 제공되었으며 객체 종속성, 순환이나 누수를 추적하는데 도움이 됩니다.
한번 정리를 하자면 아래와 같습니다.
💡 Instrument
- Allocation: 앱에서 수행된 힙 할당을 프로파일링
- Leaks: 시간이 지남에 따라 프로세스에서 메모리 누수를 확인
- VM Tracker: dirty, swapped, resident 트랙으로 나누어서 보여줌
- Virtual memory trace: 앱과 관련된 가상 메모리 시스템의 성능을 확인
Xcode의 Memory Graph Debugger
다음은 Xcode의 Memory Graph Debugger를 이용하여 실제 앱에서의 메모리를 분석해 보도록 하겠습니다.
먼저 Xcode Debug Navigator의 Memory를 선택하면, 아래 이미지처럼 현재 앱의 메모리 Footprint를 빠르게 볼 수 있습니다. 이는 위에서 언급한 앱의 전체 메모리 사이즈에 대한 그래프를 실시간으로 보여줍니다.
또한 Xcode에서 아래의 버튼을 누르면,
현재 상태에서 메모리 snapshot을 찍은 뒤, 이 snapshot의 메모리 정보를 보여주는 Memory Graph Debugger가 나타납니다.
왼쪽 패널에서는 현재 메모리에 적재되어 있는 객체들과 해당 클래스의 인스턴스 숫자들, 각 인스턴스들의 주소 목록을 보여줍니다.
위 그림에서 검정 선은 strong 레퍼런스를 나타내고, 회색 선은 unknown(weak 또는 strong) 레퍼런스를 나타냅니다. 하지만 이 그래프에서는 선택된 객체가 어떤 객체를 가리키고 있는지는 보여주지 않습니다.
메모리 그래프 디버거는 간단한 메모리 릭은 자동으로 탐지할 수 있습니다. 메모리 릭이 발견되면 보라색 !
마크로 경고를 띄워 줍니다. 클릭하면 메모리 릭이 일어난 인스턴스를 확인할 수 있습니다.
하지만 Xcode에서 모든 메모리 릭을 알려주는 것이 아닙니다. 보통 직접 찾아내야 하는 경우가 더 많습니다.
직접 찾는 방법으로는 Command Line Tool을 사용할 수 있습니다. 해당 방법에 대해서는 다음 글에 이어서 소개하도록 하겠습니다.
이번 글도 읽어주셔서 감사드리며 잘못된 내용이나 궁금하신 점이 있다면 댓글로 남겨주세요 ~ 👋🏻👋🏻👋🏻