Skip to content

About Instruments APP

In Ye, Kim edited this page Jan 7, 2025 · 2 revisions

About Instruments APP에 대한 아주 기본적인 설명입니다.

Instruments APP 사용하기

Xcode와 함께 사용되지만, Instruments App은 독립적인 앱으로 Dock에 독립적으로도 사용이 가능합니다.

1

기본 용어 및 내용

보통 Instruments가 수집하는 데이터를 트레이스 데이터라고 부른다고 합니다.

Instruments로 기록을 하는 것은 시스템 리소스를 사용하기 때문에 기록을 최소화하는 것이 관건인데요.

그래서 Last Few Seconds Mode, Windowed Mode와 같은 기능을 제공합니다.

Instruments Template List

2

편리하게 사용할 수 있도록 템플릿도 제공됩니다.

Time Profiler Template

Time Profiler 템플릿으로 간단하게 성능을 측정하면서 비교해 보겠습니다.

여기서 사용된 프로젝트는 알쏭달쏭 리팩토링 전 코드입니다.

인터페이스

들어가기 전에 인터페이스를 볼 때 자주 사용되는 기본 용어를 먼저 정리하겠습니다.

Track Viewer

3

Track은 이벤트가 발생한 곳(ex. CPU 코어, 프로세스)에 해당하는 시간 시리즈 트레이스 데이터를 나타냅니다.

  1. 가장 상단에 있는 Time Profiler는 CPU 사용량에 대한 요약입니다.
  2. 두번째 Points of interest는 특정 "이벤트"나 "작업 구간"을 추적하는 트랙입니다.
  3. Thermal State는 시스템 발열 상태입니다.
  4. Hangs는 응답이 없는 순간입니다.
  5. 마지막은 특정앱(예시에서는 알쏭달쏭)을 프로파일링하여 측정한 결과입니다.

주요한 것들을 하나씩 자세히 살펴보겠습니다.

CPU

기존 알쏭달쏭을 앱을 타겟으로하고 레코딩하면 다음과 같이 트레이스 데이터가 보여집니다.

5

hover해보면 아래와 같이 CPU 사용량도 볼 수 있습니다.

4

그래프 아래를 보면 실행중인 메소드도 볼 수 있습니다. 타임 프로파일러는 초당 여러번 스냅샷을 찍어 프로세스에서 실행중인 모든 함수를 기록하는 방식입니다.

따라서 필터된 부분에 실행중인 모든 함수를 보여주게 됩니다.

6

가장 무거운(자주호출되는) 함수도 오른쪽에서 요약해서 볼 수 있습니다.

7

흰색 프레임은 애플리케이션 자체에서 실행된 함수이며, 시스템 프레임워크나 라이브러리에서 실행된 함수는 회색으로 표시됩니다.

Signpost (How? Why? - 왜 실행되었고 어떻게 실행되었어?)

타임 프로파일러는 시간과 호출스택에 대한 상관관계를 그래프로 보여줍니다.

그러나 이러한 그래프만으로는 코드가 왜 실행되었고, 어떻게 실행되었는지 정확한 측정치를 대신하기 어렵습니다. Signpost를 사용하면 메소드가 짧게 10번 실행되었거나 길게 단번 실행되었거나.. 등등 이렇게 정확한 측정이 필요할 경우 사용할 수 있습니다.

딱 듣고 듣는 생각은 print문으로 해도 되는 거 아닌가? 라는 의문이 듭니다.

그러나 print문으로 사용할 경우 Instruments에서 확인할 수 없고 상당히 비효율적이게 됩니다.

func test() {
    print("시작")
    print("종료")
}

따라서 오늘부터는 Signpost를 사용해보도록합시다.

Instruments와 소통할 수 있는 log Handle을 만들어서 사용해줍니다.

Points of Interest 카테고리를 사용해서 로그핸들을 만들어준 예시입니다.

private func getRelatedRecords(for answer: Answer, from records: [ASEntity.Record]?, count: Int) -> [ASEntity.Record] {
      os_signpost(.begin, log: OSLog(subsystem: "kr.codesquad.boostcamp9.alsongDalsong", category: .pointsOfInterest), name: "fetchDownloadURLs")
      defer {
          os_signpost(.end, log: OSLog(subsystem: "kr.codesquad.boostcamp9.alsongDalsong", category: .pointsOfInterest), name: "fetchDownloadURLs")

      }
      //생략
  }

Instruments를 실행해서 프로파일링하면 아래처럼 함수가 호출되는 시점과 종료되는 시점을 명확하게 알 수 있게 됩니다.

9

클릭하면 더 자세한 정보도 볼 수 있습니다. 위 구간에서 총 2번 발생했고, 각 평균 시간도 보이네요.

10

Jump Bar를 바꾸면 기록된 모든 영역의 리스트를 볼 수 있습니다.

11

Hang(응답이 없는 순간)

행이란건 응답이 없는 순간을 의미합니다.

예를 들어 사용자가 버튼을 눌렀는데 그에 대한 응답이 오래 걸리면 사용자 경험이 낮아지겠죠.

그래서 행을 관리하는 것이 사용성에 있어서 아주 중요하게 됩니다.

그런데 만약에 버튼을 누르자마자 0.0001초만에 반응이 되었다면 hang이 발생한거고 그 시간이 0.0001초인걸까요?

이에 대해서 애플은 아래와 같이 설명합니다.

12
  • 0~100ms : Instant (hang이 아님)
  • 100~200ms : Circumstantial (상황에 따라 hang 으로 판단될 수 있으나, 대부분 Instant로 판단)
  • 250~500ms : Micro Hang. (hang report 에 포함됨. Instant 가 아닌 상황.)
  • 500ms~ : Hang.

근데 물론 정답은 없습니다. 예를 들어 누군가와 대화를 하고있다면 유저는 1초 정도의 delay(or hang)가 자연스럽다고 느낄 것입니다. 하지만 전구를 킨다면 상황을 달라지겠죠. 전구 ON 버튼을 눌렀는데 1초 뒤에 전구 불이 켜진다면 사용자는 불편함을 느낄 것입니다.

하지만 대부분은 Instant 상태를 목표(goal)로 삼아도 좋습니다.

결과적으로 메인스레드 작업이 100ms 내에 이뤄져야 좋다는 말입니다.

출처

https://developer.apple.com/videos/play/wwdc2019/411/

https://developer.apple.com/videos/play/wwdc2023/10248/

Clone this wiki locally