- Memory Landscape
- 메모리가 모자라면 앱이 죽을 수 있다.
- 유저는 멀티태스킹을 기대하지만, 메모리 관리를 못하면 앱이 백그라운드에서 죽을 수 있다.
- Memory Fundamentals
- 메모리가 어떻게 할당되고 관리되는가?
- 모든 앱은 동일한 주소 공간을 가지고 있다고 가정한다. -> 가상 메모리
- 메모리는 페이지 단위로 관리된다.
- 메모리에는 다양한 영역이 있다
- 힙 영역(동적 할당한 객체가 존재하는 부분) -> 앱이 주로 관심 가지는 부분
- __TEXT, __DATA
- 스레드 스택
- 이미지 데이터
- CALayer 전용 저장소
- 데이터베이스 캐시
- 메모리 타입이 왜 중요한가?
- 메모리가 모자라면 어떻게 하는가?
- 페이지를 유지하려면 이를 디스크로 보낸다(swap, page out)
- 하지만 iOS는 스와핑을 하지 않는다.
- 대신 날려버린다.
- 하지만 그냥 날리면 문제가 생긴다. 그래서 메모리를 구분한다.
- 클린 메모리: 메모리의 내용이 디스크에 있는 것. 안심하고 날려도 된다. -> 코드, 프레임워크, 메모리 매핑된 파일 등
- 더티 메모리: 메모리의 내용이 디스크에 없는 것. -> 동적 할당된 객체, 압축이 해제된 이미지, 데이터베이스 캐시 등
- 어떤게 클린하고 더티한가?
- NSString: 리터럴로 바로 초기화하면 클린하다. 객체로 만들려고 하면 더티해진다.
- malloc: 메모리를 할당만 한 상태면 클린하지만, 거기에 값을 쓰면 더티해진다.
- 이미지: 압축을 풀게 되면 더티해진다.(보여주려면 압축을 풀어야된다)
- 결론: 대부분의 앱에서 일어나는 할당은 더티하다.
- 시스템의 메모리 관리
- 더티 페이지가 늘어나면서 메모리 압력(Memory Pressure)를 받게 된다
- 이 과정에서 압력을 해소하기 위해 백그라운드 앱들을 죽이게 된다. 그리고 해당 앱들이 사용하던 더티한 데이터들은 모두 프리 상태로 바뀌게 된다.
- 이후 새로운 앱이 늘어나면서 클린한 영역이 다시 늘어나게 된다.
- 메모리 경고
- 메모리가 한정된 디바이스에서는 필연적인 것
- UX를 유지할 수 있는 마지노선
- 앱이 다음 이벤트에 반응할 수 있어야 한다.
- 메인스레드에서 날아오는 노티피케이션
- 큰 메모리를 자주 할당하는 것은 피해야 한다.
- 백그라운드로 진입할 때, 정리할 수 있는 것들은 정리해야 한다.
- 어떻게 대처하는가?
- 최대한 데이터를 해제한다. -> 유저 경험을 해치지 않는 선에서
- 다음 이벤트들에 반응한다.
- UIApplicationDidReceiveMemoryWarningNotification
- appDelegate.applicationDidReceiveMemoryWarning
- viewController.didReceiveMemoryWarning -> 메모리에 있는 뷰컨 모두에 대해서 불리는가?
- viewDidUnload는 deprecated
- 디바이스의 메모리 제한
- 여러 디바이스에서 테스트될 필요가 있다.
- 가능하면 적게 쓰자
- 스파이크 패턴의 메모리 사용을 주의하라
- 치솟았다가 떨어지고 치솟았다가 떨어지고 하는 패턴
- 일정 수준을 계속 유지해주는 게 좋다 -> autoreleasePool이 도움이 된다.
- RC 방식이 최대 정지 시간이 크지 않으니 그때 그때 해결하도록 하는게 좋다는 것이다.
- 더티 메모리는 대부분 힙과 관련되어 있다.
- 메모리 사용량 증가를 줄이려면 다음을 주의하라
- 누수 메모리
- 버려진 메모리: 낭비된 메모리
- 캐시 메모리
- 반복적인 행동이 메모리 증가를 유발하지 않는지 살펴보라
- 리소스를 가지고 있는 객체를 주의깊게 보자 -> 큰 데이터나 많은 객체를 들고 있을 가능성이 높다.
- 커스텀 객체를 주의깊게 보자
- 메모리 워닝을 시뮬레이트해보자