티스토리 뷰

반응형

WWDC 23 > Analyze hanges with Instruments  를 기반하고 있습니다.

(40분 쯤 되는데 너무 재밌고 유용함. 강추) 

 

# Hang

hang 은 delay 를 의미한다고 생각하면 됩니다.

Xcode Instruments 에서 녹화버튼을 꾹 누르고 Recording Options 에 가보면 

 

 

 

Hang, MicroHang 등 애플이 몇초 기반으로 정의해뒀는 지 볼 수 있고

프로파일링할때 어디까지 리포트되게 할 건지 설정가능합니다. 

 

 

 

# Hang 만들어보기 

 

Hang 을 유발할 코드를 만들어봅시다.

struct ContentView: View {
    
    @State private var showImagePicker = false
    
    var body: some View {
        Button(action: {
            showImagePicker = true
        }, label: {
            Text("이미지 피커")
        })
        .sheet(isPresented: $showImagePicker) {
            ImagePicker()
        }
    }
}

struct ImagePicker: View {

    var body: some View {
        ScrollView {
            HStack {
                ForEach(0..<1000) { i in
                    DummyImageView()
                }
            }
        }
}

struct DummyImageView: View {

    let potatoImageUrlString = "https://i.namu.wiki/i/xqZXxdDm2FGg7jdsA3VcmR2RMyn8LSzyxPXj1lHcQC_Qhy1bBSxNS5sZcXIG5bQpMVxzG4YMtArPkjkAWFDN0BdGoXhCUluNe863yLGQ3pbuWjSw1nvBEpMF5xvd8BbDe98PDsGla2OWognYzwvDlg.webp"
    
    var body: some View {
        AsyncImage(url: URL(string: potatoImageUrlString)) { image in
            image.resizable()
        } placeholder: {
            ProgressView()
        }
        .frame(width: 100, height: 100)
    }
}

 

이미지 피커 버튼을 누르면 hang 이 발생합니다.

 

 

 

 

 

# Instruments 와 함께 Hang 해결하기 

 

Profile 버튼을 눌러서 Instruments > Time Profiler 를 열어줍니다. 

 

 

 

 

SwiftUI 앱이므로 같이 보기 좋은 도구도 추가해줍니다.

View Body 를 추가해줍니다. 

 

 

 

 

그리고 레코딩 버튼을 눌러줍니다.

Severe Hang 발생함을  볼 수 있습니다.  

 

 

 

 

멈춤을 누르고 옵션 + 우클릭해서 Severe Hange 구간을 확대해줍니다.

 

 

 

 

 

My App > Main Thread 를 열어봅니다. 

 

 

 

두가지 타입의 Hang 중에서 Busy Main Thread 임을 먼저 확인합니다. 

 

 

 

또한 MainThread 에 가보면 많은 작업들이 수행되고 있고 

(+ Hide System Libraries 를 하면 System Call Stack 을 숨길 수 있습니다.)

 

 

 

 

SwiftUI > View Body 로 가보면 

AsyncImage body count가 매우 많이 호출되고 있음을 알 수 있습니다. 

 

 

Busy Main Thread 는 한 작업이 오래걸리는 게 아니라 여러 작업이 많이 발생해서 임을

인지합니다. (Too Long 이 아니라 Too Often)

 

 

 

AsyncImage 가 많이 호출됨이 원인임을 알았으니 코드를 수정해줍니다.

LazyHStack 을 안해줬구나.. 깨닫고 코드를 수정해줍니다.  (살짝 억지이긴 한데..-_- 예제니까..)

struct ImagePicker: View {

    var body: some View {
        ScrollView {
            LazyHStack {
                ForEach(0..<1000) { i in
                    DummyImageView()
                }
            }
        }
 }

 

 

다시 프로파일링을 해보면 여전히 body count 가 그대로인 것을 볼 수 있습니다.

 

 

ScrollView direction 을 빼먹었음을 깨닫고 코드를 수정해줍니다.

 

struct ImagePicker: View {
    
    var body: some View {
        ScrollView(.horizontal) {
            LazyHStack {
                ForEach(0..<1000) { i in
                    DummyImageView()
                }
            }
        }
 }

 

 

다시 프로파일링을 해보면  

SwiftUI body count도 줄고 

Hang 도 없어진 것을 볼 수 있습니다.

 

 

 

+ WWDC 후반부에는 Task 관련 Hang 개선도 나오니 참고..!  

 

 

 

[ 더 보면 좋을 것 ] 

 

https://developer.apple.com/wwdc22/10082

 

Track down hangs with Xcode and on-device detection - WWDC22 - Videos - Apple Developer

Learn how you can increase responsiveness and eliminate hangs in your app and make even better experiences. Hang out with the Performance...

developer.apple.com

 

 

https://developer.apple.com/documentation/xcode/understanding-hangs-in-your-app

 

Understanding hangs in your app | Apple Developer Documentation

Determine the cause for delays in user interactions by examining the main thread and the main run loop.

developer.apple.com

 

 

 

 

 

 

 

 

반응형
댓글