swift

Memory Debugging(leak Test)

motosw3600 2022. 2. 20. 20:09

Memory Debugging

ios에선 메모리 관리를 유의해야 한다. 특히 ARC를 사용한 메모리 자동 참조/해제를 하기 때문에 컴파일 타임때 효과적인 메모리 관리를 할순 있지만 retain cycle에 의한 해제되지 못한 메모리들은 앱에 계속 남아있어 메모리누수가 발생할 수 있다.

Xcode에서 메모리를 분석할 수 있는 여러 방식들이 있다.

 

Xcode Memory Graph Debugger

현재 사용중인 memory에 대해 Footprint를 확인할 수 있다. 

앱의 전체 메모리 사이즈에 대한 그래프를 실시간으로 확인할 수 있다.

하단의 debug memory graph버튼을 클릭해 memory graph도 확인할 수 있다. 

 

왼쪽에서 현재 메모리에 포함되어 있는 객체들과 해당 클래스의 인스터스 및 주소를 확인할 수 있다.

 

memory graph에서 굵고 진한선은 객체간 강한참조(strong reference)를 이루고있고

회색의 선은 객체간 약한참조(weak reference)를 구성하는것을 확인할 수 있다.


Memory Snapshot(Command Line)

memory graph debugger중 Xcode상단의 File -> Export Memory Graph를 누르면 현재 메모리상태를 스냅샷으로 저장할 수 있다.

vmmap명령어를 사용하여 저장한 memory snapshot파일을 확인할 수 있다.

 

VIRTUAL SIZE: 앱이 원하는 모든 메모리

RESIDENT SIZE: 실제 메모리에 로드되는 메모리

DIRTY SIZE: 앱에 할당한 메모리

SWAPPED SIZE: Compressed Size를 의미하며 Memory Compressor에 압축되기 전 Size

 

Memory Leak Example

실제로 예제로 Memory Leak을 발생한뒤 Memory를 분석해보자.

ViewController와 SecondViewController를 만들고 Next버튼을 누르면 ViewController -> SecondViewController로 push되도록 설정

 

SecondViewController에서 MockView의 delegate를 강한참조되도록 설정하여 MockView와 retainCycle이 이뤄지도록 설정

protocol DefaultDelegate {
    func delegateMethod()
}

class MockView: UIView {
    var delegate: DefaultDelegate?
}

class SecondViewController: ViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let mockView = MockView()
        // strong reference
        mockView.delegate = self
        view.addSubview(mockView)
    }
}

extension SecondViewController: DefaultDelegate {
    func delegateMethod() {
        print("delegate implementation")
    }
}

 

SecondViewController를 계속 띄웠다 반복하고 Memory graph를 확인해보자.

약 20번정도 반복하고 memory Use의 사용량은 위와같이 증가하였고

MockView의 메모리 인스턴스가 해제되지 않고 남아있는것을 볼 수 있다.

 

 

위의 메모리 leak을 해결하기 위해 MockView의 delegate를 약한참조가 되도록 설정해보자.

...

class MockView: UIView {
    weak var delegate: DefaultDelegate?
}

...

SecondViewController가 MockView의 delegate를 약하게 참조하고 있으므로 SecondViewController가 해제될때 메모리에 남아있지 않고 같이 해제된다.

여러번 반복했을때 Memory graph에서 MockView의 인스턴스가 해제되었음을 확인할 수 있다.

 

참고:

https://github.com/seizze/sample-projects-for-blog

https://medium.com/zendesk-engineering/ios-identifying-memory-leaks-using-the-xcode-memory-graph-debugger-e84f097b9d15

'swift' 카테고리의 다른 글

Tuist로 프로젝트 관리해보기  (0) 2022.03.05
The Composable Architecture(TCA)  (0) 2022.03.02
DispatchSemaphore  (0) 2022.02.06
UICollectionView Custom Layout  (0) 2022.02.03
Dynamic Cell Size CollectionView  (0) 2022.01.25