관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 3. Memory Deep Dive - Memory Footprint (페이징, Compressed 메모리, NSCache vs Dictionary) 본문

iOS 응용 (swift)

[iOS - swift] 3. Memory Deep Dive - Memory Footprint (페이징, Compressed 메모리, NSCache vs Dictionary)

jake-kim 2023. 12. 10. 01:04

* 가장 기초) iOS 메모리 기초 개념 - virtual memory, dirty memory, clean memory, compressed memory, swapped memory 이해하기 포스팅 글

 

1. Memory Deep Dive - iOS 메모리 운영체제 기초 (가상 메모리, 페이징, clean memory, dirty memory, compressed memory)

2. Memory Deep Dive - Memory를 줄여야 하는 이유 (+ 앱 메모리 사용량 아는 방법)

3. Memory Deep Dive - Memory Footprint (페이징, Compressed 메모리, NSCache vs Dictionary)

4. Memory Deep Dive - Memory Footprint 프로파일링 방법 (Allocation, Leaks, VM Tracker, Virtual memory trace)

5. Memory Deep Dive - Memory Footprint 프로파일링 방법 (2) (Xcode Memory Debugger, Memory Graph, Memgraph)

6. Memory Deep Dive - Memory Footprint 프로파일링 방법 (3) (vmmap, leaks, heap, malloc_history)

7. Memory Deep Dive - 이미지 로드 매커니즘, 이미지 핸들링 최적화 (UIGraphicsBeginImageContextWithOptions, UIGraphicsImageRenderer)

8. Memory Deep Dive - 이미지 리사이징, 이미지 다운 샘플링 (ImageIO, ImageSource)

9. Memory Deep Dive - 백그라운드에서 메모리 최적화하는 방법

메모리 관리

  • 전 포스팅 글에서 알아보았듯이, 메모리는 페이징 이라는 것을 사용하여 관리
  • 힙 메모리 안에서 page하나당 여러개의 UIView, String과 같은 인스턴스를 관리하거나 여러 페이지에 Data가 걸쳐있는 경우가 존재

https://developer.apple.com/videos/play/wwdc2018/416/

  • 일반적으로 page 하나당 크기는 16K이며, clean되거나 dirty 될 수 있음
    • clean: 데이터가 아직 사용되지 않음
    • dirty: 데이터가 사용됨
  • 앱의 메모리 사용량 = page 수 * 페이지 크기 (16K)

-  https://developer.apple.com/videos/play/wwdc2018/416/

  • ex) Int 배열을 힙에 할당했을때 동작

  • 메모리 사용 관점 - 만약 위 데이터를 6개의 페이지를 통해 관리할 경우?
    • 20000개의 정수 배열 할당 -> 힙 영역에 clean memory 상태로 저장
    • 0번째 인덱스에는 32, 19999인덱스에는 64를 할당 -> 데이터 버퍼에 write하기 시작하면 0번째 인덱스와 19999번째 인덱스를 갖고 있는 page는 dirty상태로 변함
    • (즉 0과 19999인덱스에 영향을 받아서 1페이지와 6페이지 영역이 dirty 상태로 변함)

또 다른 예) jpg 파일을 메모리에 저장하는 경우

  • 50KB .jpg파일을 저장할 때, 한 페이지 당 16KB이기 때문에 4페이지가 필요
  • 이때 마지막 4번째 페이지는 공간이 남아있으므로 다른 데이터 저장이 가능 (단, 해당 페이지가 clean 상태여야 사용이 가능)



메모리가 dirty, clean 상태에 따라 알 수 있는 것

  • 프로퍼티를 사용할 때 setter로 선언하지 않고 getter로만 선언하면 page가 항상 clean 상태로 유지됨

앱 메모리 Clean 개념

  • page out될 수 있는 메모리
  • * page out: 가상메모리에서 프로세스가 필요로 하는 데이터를 물리적인 메모리에 올리고(unload) 필요 없는 데이터는 디스크에 내보냄(page out)으로써 메모리를 효율적으로 사용하는데 여기서의 page out을 의미
  • 프레임워크도 페이징이 될 수 있음
  • clean 상태가 되면 스위즐링도 가능

앱 메모리 Dirty 개념

  • 할당된 메모리
  • 프레임워크도 dirty상태가 될 수 있음

앱 메모리 Compressed 개념

  • iOS 7부터 도입
  • 사용되지 않은 메모리를 가져와서 압축하여 더욱 많은 메모리를 사용하게끔 만드는 원리
  • 액세스할 시점에는 다시 압축을 풀어서 접근함

ex) 캐싱을 위해 Dictionary가 있을때, 여기에 총 5페이지 중 2페이지만 사용하는 경우

  • 3페이지는 액세스하지 않았기 때문에 3페이지를 하나의 페이지로 압축함

Memory Warnings과 Compressed Memory

  • Compressed memory는 이전보다 더 많은 메모리를 사용할 수 있기 때문에 메모리 해제를 복잡하게 만듦
    • 때문에 메모리 경고가 발생할 때 잠시 아무것도 캐싱하지 않거나, 일부 백그라운드 작업을 제한하는 작업이 권장

didReceiveMemoryWarning() 핸들링

  • 앱 메모리 경고 메서드가 있지만, 보통 핸들링하지 않는 경우가 있는데 실제로는 여기서 메모리 관련 처리가 필요함
// AppDelegate.swift

func applicationDidReceiveMemoryWarning(_ application: UIApplication) {
    
}
  • iOS7부터 Compressed Memory를 사용하여, 이전보다 더 많은 메모리를 사용할 수 있고 메모리 해제가 복잡한데 이 영향에 의하여 메모리 경고 처리가 필요함
  • 캐싱을 제거하는 방법이 가장 쉽고 간편한 방법

Dictinoary가 아닌 NSCache로 캐싱해야 하는 이유

  • didReciveMemorywarning()을 다루기 전에 먼저, 캐싱을 할때 NSCache와 Dictinoary를 사용할 수 있는데 NSCache를 사용하는 것이 thread-safe하므로 NSCache가 안전함
  • NSCache가 메모리를 할당하는 방식에 있어서 더욱 purgeable 함 (=더욱 메모리 제거가 쉬움)
  • 메모리가 부족하다는 델리게이트 메서드가 있는데 여기에서 메모리를 관리하는 방법?
    • NSCache를 사용하고 있다면, didReceiveMemoryWarning에서 cache의 데이터들을 removeAllObjects()하여 핸들링이 필요

* 참고

- https://developer.apple.com/videos/play/wwdc2018/416/

Comments