iOS Memory Deep Dive Part 1

Tabber·2023년 8월 5일
1

iOS Memory Deep Dive

목록 보기
1/3
post-thumbnail

iOS 메모리에 대해 심층 분석을 해보자.
해당 글의 원본 내용은 WWDC18 - iOS Memory Deep Dive 입니다.

이번에 WWDC 18 세션 중 iOS Memory Deep Dive 세션을 보면서 공부한 내용들을 정리해보기 위해 이 글을 적었다.

이 글은 총 3개의 글로 이루어질 예정이다.

Part 1은 iOS 메모리 심층 분석에 초점을 맞추었고,
Part 2는 footprint를 프로파일링 하는 방법에 대해 소개,
Part 3는 알아본 내용으로 실제 메모리 관리, 프로파일링을 해보는 것으로

글을 마무리 짓겠다.

메모리를 왜 줄여야 하는가?

사실 이 질문에 대한 답은 간단하다.
앱을 사용하는 사용자가 더 나은 경험을 할 수 있기 때문이다.

앱이 더 빠르게 실행되고, 시스템 또한 더 잘 동작한다. 앱이 더 오래 메모리에 유지될 수 있고, 다른 앱들 또한 우리가 절약한 공간에 더 오래 있을 수 있다.

iOS 앱 개발을 하며 항상 고민하는 이슈 중 하나가 바로 메모리에 관한 이슈라고 생각한다. 어떻게 하면 더 적게, 더 빠르게, 용량의 이슈가 없게 UI에 매끄럽게 표시하고 사용자가 사용함에 있어서 불편함이 없게 만들까 라는 고민을 하게 된다.

그냥 단순하게 생각했을 때, "메모리 그거 그냥 이미지 용량만 줄이면 되는거 아냐?", "사용하고 바로 지우기만 하면 되는거잖아!", "메모리를 제때 제때 해제 시켜주면 됨 ㅋㅋ" 라는 얘기를 하는데, 다들 가슴에 손을 얹고 생각해보자.

"메모리 관리를 잘 하고 있는가?"
나는 솔직히 말해 잘 하고 있지 않는 사람 중 하나라고 생각한다. 유지는 OS 단에서 알아서 해주는 정도까지만 생각하고 하는정도..

그래서 이번 기회에 iOS에서는 어떻게 메모리를 관리하고, 메모리를 많이 사용하는 곳을 찾으려면 어떻게 하면 되는지 알고 싶어서 이 세션을 보게 되었다.

다 같이 한번 딥-하게 살펴보자!

앱이 사용하고 있는 메모리를 확인해보자

메모리를 확인하기 위해서는 우리가 사용하고 있는 메모리 페이지를 살펴봐야 한다.
위 사진에서 처럼 시스템에서 제공하는 메모리 페이지는 Heap에 여러 객체를 저장할 수 있다. 그리고 일부 객체는 여러개의 페이지에 걸쳐 있을 수도 있다.

일반적으로 페이지의 크기는 16KB이고 보통 Clean 하거나 Dirty 하다.

앱의 메모리 사용량은 실제로 페이지 수에서 페이지 크기를 곱한 것이다.

Clean Page와 Dirty Page의 예시로 20,000개의 정수 배열을 할당한다고 가정을 해보자. 그럼 시스템에서는 총 6개의 페이지를 제공해준다.

6개의 페이지는 모두 Clean Page 상태로 제공이 된다. 그러나 이제 데이터 버퍼에 Write 하기 시작하면 해당 페이지는 Dirty Page가 된다.

위의 사진에서는 첫번째 위치와 마지막 위치에 대한 Page가 Dirty Page가 된다.

Write 한 페이지 이외의 페이지들은 여전히 Clean 상태로 유지가 된다.

또 다른 흥미로운 얘기는 메모리에 Mapping이 된 파일이다. 파일은 디스크에 존재하지만 메모리에 로드가 된다. 읽기 전용 파일을 사용하면 항상 Clean Page가 된다. 커널은 디스크에서 RAM으로 들어오고 나갈 때 실제로 관리하게 된다.

이걸 설명하기 좋은 예는 JPEG 이다.
예를 들어 크기가 50KB인 JPEG이 있는 경우 메모리가 매핑될 때 실제로 메모리의 4개의 Page에 매핑된다. 마지막 페이지인 4번째 페이지는 완전히 채워지지 않은 페이지이므로 다른 용도로도 사용이 가능하다.
그러나 앞의 3개의 페이지는 시스템에서 항상 제거할 수 있다. (다른 용도로 사용하지 못하는 메모리는 OS 단에서 메모리 관리를 위해서 지워질 수 있다라는 소리 같다.)

우리가 일반적으로 앱에 대해 얘기할 때 해당 Footprint와 profile에는 Dirty,Commpressed, Clean 한 메모리 세그먼트가 존재한다.

이것들을 하나씩 살펴보자.

Clean Memory


Clean Memory 는 페이지 Out(기록) 될 수 있는 데이터이다.
아직 기록이 되지 않고 있기에 디스크의 데이터와 동일하다.
예를 들어 위 사진에서 볼 수 있듯, 이미지, 데이터, 모델 등등 말이다.

또한 프레임워크도 될 수 있다. 모든 프레임워크에는 DATA CONST 섹션이 존재한다.

Dirty Memory

Dirty Memory는 앱에 의해 쓰여진 메모리를 말한다.
Heap의 메모리 할당, Array, Strings, Cache, 프레임워크 등등이 해당된다.
Decode된 이미지 버퍼일 수도 있는데, 이 얘기는 뒤에서 더 자세히 하겠다.

Compressed Memory

Compressed Memory는 꽤 멋진데, iOS에는 전통적인 디스크 스왑 시스템이 없다고 한다. 대신에 Memory Compressor를 사용한다.
Memory Compressor는 iOS 7부터 도입되었다고 한다

디스크 스왑?
물리적 메모리(RAM)의 용량이 가득 차게 될 경우 하드 디스크 공간을 메모리 공간처럼. 교환(swap)하여 사용하는 것.

Memory Compressor는 아직 엑세스 되지 않은 페이지를 압축하여 실제로 더 많은 공간을 만들 수 있다. 반대로 메모리를 엑세스할 상황이 오면 압축을 해제한다.

위 사진을 보며 캐싱에 사용하는 Dictionary가 있다고 가정해보자. 지금 당장은 3페이지의 메모리를 사용하지만, 한동안 액세스 하지 않을 경우 한페이지로 압축할 수 있다.
압축을 한 결과 3개의 페이지를 사용하던 페이지를 한개의 페이지로 줄이고 나머지 2개의 페이지의 공간이 생긴 결과를 볼 수 있다.

만약 다시 액세스 할 상황이 생긴다면 다시 압축을 해제할 것이다.


Memory Warning

잠시 메모리 Warning에 대해 얘기해보자. 앱에서 뜨는 Memory Warning이 항상 우리 앱이 원인은 아니다. 메모리가 부족한 기기를 사용하면서 중간에 전화를 받는다거나, 메세지를 보낸다거나 하면 메모리 Warning이 발현될 수 있으며 사용이 중지될 수도 있다. 따라서 항상 우리의 앱이 문제라는 상황은 가정하지 말자라는 얘기다.

따라서 Memory Compressor는 압축된 내용에 따라서 실제로 이전보다 더 많은 메모리를 사용할 수도 있기 때문에 메모리 해제를 복잡하게 만든다. 따라서 메모리 Warning이 발생했을 때 캐싱을 수행하지 않거나, 일부 백그라운드 작업을 제한하는 것과 같은 정책을 변경하는 방법을 권장한다.

이런 상황을 시도해볼 수 있다.
메모리 Warning을 받고 캐시에서 모든 객체를 제거하기로 결정하는데,그럼 압축된 Dictionary의 예시로 돌아가면 어떤 상황이 벌어질까?

Dictionary를 압축하기 전에는 사실 더 많은 페이지를 사용하고 있다.

그리고 모든 객체를 제거하고 있기 때문에 압축되었을 떄의 한 페이지로 되돌리기 위해 또 많은 작업을 수행해야 한다. 따라서 우리는 일반적으로 메모리 Warning에 대해 정말 주의헤야 한다.


캐시의 경우 NSCache를 사용하게 되면, 데이터를 thread safe(여러 쓰레드에서 동시에 접근해도 안전하다)하게 저장할 수 있고, 메모리에 저장된 데이터는 항상 purgeable(버릴 수 있는)하기 때문에 NSDictionary보다 NSCache를 사용하는 것을 권장한다.

다시 Memory profile로 돌아와서 3가지의 섹션들이 있는데, 실제로는 앱의 Memory에 대해 얘기할 때에는 Dirty, Compressed 세그먼트에 대해서만 얘기하고 있다.

모든 앱에는 공간의 제한(footprint limit)이 있다.

  • 이 제한은 앱의 경우에는 상당히 높긴 하지만, 기기에 따라서 제한이 변경된다는 점을 유의해야 한다.
  • 익스텐션은 메모리 공간이 훨씬 적기 때문에 사용할 때 더욱 주의해야 한다.

footrpint를 초과하면 Exception이 발생한다.
이러한 예외는 EXC_RESOURCE_EXCEPTION 이다.


정리

이번 글에서는 iOS가 메모리를 어떻게 할당하고, 어떠한 방식으로 가지고 있는지에 대해 알아보았다.
Dirty Page, Clean Page가 있는 것을 알게 되었고, iOS는 기본적으로 Swap을 하지 않고 Compressed 하는 방식으로 메모리 관리를 하는 것을 알 수 있었다.

모든 앱에는 제한적인 공간이 존재하고, 기기의 성능에 따라서 용량이 달라진다는 것을 알 수 있었다.

다음 글에서는 footprint를 프로파일링 하여 메모리를 뜯어볼 수 있는 방법에 대해 알아보겠다.

profile
iOS 정복중인 Tabber 입니다.

2개의 댓글

comment-user-thumbnail
2023년 8월 5일

잘 읽었습니다. 좋은 정보 감사드립니다.

1개의 답글