관리 메뉴

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

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

iOS 응용 (swift)

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

jake-kim 2023. 12. 9. 01:20

* 가장 기초) 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 메모리)

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 - 백그라운드에서 메모리 최적화하는 방법

Memory를 줄이는 한가지 목적

  • 사용자에게 더 나은 사용 경험을 제공

앱 Memory를 줄이면 얻을 수 있는 것들

  • 앱이 빠르게 실행됨 (launch faster)
  • 시스템 성능이 증가 (system performance)
  • 자기 자신의 앱은 물론이고, 다른 앱들까지 메모리에 더 오래 유지되게함
    • 앱을 백그라운드에 놓았을때 메모리를 많이 사용하면 자동으로 앱이 종료되는데, 만약 A앱의 메모리 사용량이 높으면 A앱 뿐만이 아닌 다른 앱도 메모리에서 내릴 수 있다는 점

사용중인 메모리 확인 방법

* 코드 참고: https://gist.github.com/pejalo/671dd2f67e3877b18c38c749742350ca

  • 코드를 보면 아래처럼 가져올 수 있는데 여기에서 핵심적인 부분만 확인하여 분석
func getMemoryUsedAndDeviceTotalInMegabytes() -> (Float, Float) {
        
    // https://stackoverflow.com/questions/5887248/ios-app-maximum-memory-budget/19692719#19692719
    // https://stackoverflow.com/questions/27556807/swift-pointer-problems-with-mach-task-basic-info/27559770#27559770
    
    var used_megabytes: Float = 0
    
    let total_bytes = Float(ProcessInfo.processInfo.physicalMemory)
    let total_megabytes = total_bytes / 1024.0 / 1024.0
    
    var info = mach_task_basic_info()
    var count = mach_msg_type_number_t(MemoryLayout<mach_task_basic_info>.size)/4
    
    let kerr: kern_return_t = withUnsafeMutablePointer(to: &info) {
        $0.withMemoryRebound(to: integer_t.self, capacity: 1) {
            task_info(
                mach_task_self_,
                task_flavor_t(MACH_TASK_BASIC_INFO),
                $0,
                &count
            )
        }
    }
    
    if kerr == KERN_SUCCESS {
        let used_bytes: Float = Float(info.resident_size)
        used_megabytes = used_bytes / 1024.0 / 1024.0
    }
    
    return (used_megabytes, total_megabytes)
}
  • 디바이스의 전체 메모리 가져오기
ProcessInfo.processInfo.physicalMemory // Bytes
  • swift내장된 Darwin이라는 프레임워크 안에 mach_task_basic_info라는 구조체를 통해 손쉽게 resident_size(사용중인 bytes)값 구하기가 가능

응용

  • 메모리 값을 실시간으로 확인하기 위해서 display link를 사용하여 실시간으로 메모리를 출력하도록 구현
  • 해당 부분
private func startDisplayLink() {
    stopDisplayLink()
    displayLink = CADisplayLink(target: self, selector: #selector(recordMemory))
    displayLink?.preferredFramesPerSecond = 10
    displayLink?.add(to: .main, forMode: .default)
}

private func stopDisplayLink() {
    displayLink?.invalidate()
    displayLink = nil
}

@objc private func recordMemory() {
    let val = round(getMemoryUsedAndDeviceTotalInMegabytes().0)
    label.text = "\(val)"
}

결과)

  • mb단위의 메모리 표시를 중앙의 UILabel로 표현하고, 버튼을 누르거나 background로 이동할 때 메모리의 변화량 관찰이 가능

* 전체 코드: https://github.com/JK0369/ExMemory_

* 참고

- https://gist.github.com/pejalo/671dd2f67e3877b18c38c749742350ca

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

Comments