Macrobenchmark 작성

애플리케이션 시작과 복잡한 UI 조작(RecyclerView 스크롤 또는 애니메이션 실행)과 같이 애플리케이션의 대규모 사용 사례를 테스트하는 데 Macrobenchmark 라이브러리를 사용합니다. 코드의 작은 영역을 테스트하려면 Microbenchmark 라이브러리를 참고하세요.

라이브러리는 Android 스튜디오 콘솔과 JSON 파일 양쪽에 자세한 정보가 포함된 벤치마킹 결과를 출력합니다. 또한 Android 스튜디오에서 로드하고 분석할 수 있는 트레이스 파일도 제공합니다.

지속적 통합에서 벤치마크 실행에 설명된 대로 지속적 통합(CI) 환경에서 Macrobenchmark 라이브러리를 사용합니다.

Macrobenchmark를 사용하여 기준 프로필을 생성할 수 있습니다. 아래 가이드에 따라 Marcobenchmark 라이브러리를 설정한 다음 기준 프로필을 만듭니다.

프로젝트 설정

최신 버전의 IDE에는 Macrobenchmark와 통합된 새로운 기능이 있으므로 Macrobenchmark는 최신 버전의 Android 스튜디오와 함께 사용하는 것이 좋습니다.

Macrobenchmark 모듈 설정

Macrobenchmark는 앱 코드와 분리되어 앱 측정 테스트 실행을 담당하는 com.android.test 모듈이 필요합니다.

Android 스튜디오에는 Macrobenchmark 모듈 설정을 간소화할 수 있는 템플릿이 있습니다. 벤치마킹 모듈 템플릿은 샘플 시작 벤치마크를 포함해 앱 모듈에서 빌드한 앱을 측정할 수 있는 모듈을 프로젝트에 자동으로 생성합니다.

모듈 템플릿을 사용하여 새 모듈을 만들려면 다음 단계를 따르세요.

  1. Android 스튜디오의 Project 패널에서 프로젝트 또는 모듈을 마우스 오른쪽 버튼으로 클릭하고 New > Module을 클릭합니다.

  2. Template 창에서 Benchmark를 선택합니다.

  3. 새로운 macrobenchmark 모듈의 패키지 및 모듈 이름 외에도 타겟 애플리케이션(벤치마킹할 앱)을 맞춤설정할 수 있습니다.

  4. Finish를 클릭합니다.

벤치마크 모듈 템플릿

애플리케이션 설정

앱(Macrobenchmark의 타겟이라고 함)을 벤치마크하려면 앱이 profileable이어야 합니다. 그래야 성능을 저하하지 않으면서 자세한 트레이스 정보를 읽을 수 있습니다. 모듈 마법사가 앱의 AndroidManifest.xml 파일에 자동으로 <profileable> 태그를 추가합니다.

벤치마크된 앱은 가능한 한 출시 버전(또는 프로덕션)에 가깝게 구성합니다. 앱을 디버깅이 불가능하고 가급적 압축되도록 설정하면 성능이 향상됩니다. 이 작업은 일반적으로 실행은 동일하지만 디버그 키로 로컬에서 서명된 출시 변형의 복사본을 만들어 실행합니다. 또는 initWith를 사용하여 Gradle에 작업을 실행하도록 지시할 수 있습니다.

Groovy

buildTypes {
    val release = getByName("release") {
        isMinifyEnabled = true
        isShrinkResources = true
        proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
    }

    create("benchmark") {
        initWith(release)
        signingConfig = signingConfigs.getByName("debug")
        proguardFiles("benchmark-rules.pro")
    }
}

Kotlin

buildTypes {
    getByName("release") {
        isMinifyEnabled = true
        isShrinkResources = true
        proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"))
    }

    create("benchmark") {
        initWith(getByName("release"))
        signingConfig = signingConfigs.getByName("debug")
    }
}

Gradle 동기화를 실행하고 왼쪽에 있는 Build Variants 패널을 열고 앱과 Macrobenchmark 모듈의 벤치마크 변형을 각각 선택합니다. 그러면 벤치마크를 실행하여 앱의 정확한 변형을 빌드하고 테스트할 수 있습니다.

벤치마크 변형 선택

(선택사항) 다중 모듈 애플리케이션 설정

앱에 Gradle 모듈이 2개 이상 있는 경우 빌드 스크립트가 컴파일할 빌드 변형을 알고 있어야 합니다. 해당하는 변형을 모르면 새로 추가된 benchmark buildType으로 인해 빌드가 실패하고 다음과 같은 오류 메시지가 표시됩니다.

> Could not resolve project :shared.
     Required by:
         project :app
      > No matching variant of project :shared was found.
      ...

matchingFallbacks 속성을 :macrobenchmark:app 모듈의 benchmark buildType에 추가하여 문제를 해결할 수 있습니다. 나머지 Gradle 모듈은 이전과 동일한 구성이면 됩니다.

Groovy

benchmark {
    initWith buildTypes.release
    signingConfig signingConfigs.debug

    matchingFallbacks = ['release']
}

Kotlin

create("benchmark") {
    initWith(getByName("release"))
    signingConfig = signingConfigs.getByName("debug")

    matchingFallbacks += listOf('release')
}

프로젝트에서 빌드 변형을 선택할 때, 다음 이미지에 보이는 것처럼 :app:macrobenchmark 모듈에는 benchmark를, 앱에 있는 다른 모듈에는 release를 선택합니다.

buildType으로 release 및 benchmark가 선택된 다중 모듈 프로젝트의 벤치마크 변형

자세한 내용은 변형 인식 종속 항목 관리를 참고하세요.

(선택사항) 제품 버전 설정

앱에 여러 제품 버전이 설정되어 있는 경우 빌드 및 벤치마킹할 앱 제품 버전을 알 수 있도록 :macrobenchmark 모듈을 구성해야 합니다. 이 구성이 없으면 여러 Gradle 모듈과 유사한 빌드 오류가 발생할 수 있습니다.

Could not determine the dependencies of task ':macrobenchmark:connectedBenchmarkAndroidTest'.
> Could not determine the dependencies of null.
   > Could not resolve all task dependencies for configuration ':macrobenchmark:benchmarkTestedApks'.
      > Could not resolve project :app.
        Required by:
            project :macrobenchmark
         > The consumer was configured to find a runtime of a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'benchmark', attribute 'com.android.build.api.attributes.AgpVersionAttr' with value '7.3.0'. However we cannot choose between the following variants of project :app:
             - demoBenchmarkRuntimeElements
             - productionBenchmarkRuntimeElements
           All of them match the consumer attributes:
           ...

이 가이드에서는 다음 스니펫에서 볼 수 있듯이 :app 모듈에서 demoproduction, 이렇게 두 가지 제품 버전을 사용합니다.

Groovy

flavorDimensions 'environment'
productFlavors {
    demo {
        dimension 'environment'
        // ...
    }

    production {
        dimension 'environment'
        // ...
    }
}

Kotlin

flavorDimensions += "environment"
productFlavors {
    create("demo") {
        dimension = "environment"
        // ...
    }
    create("production") {
        dimension = "environment"
        // ...
    }
}

벤치마킹을 여러 제품 버전으로 구성하는 방법에는 두 가지가 있습니다.

missingDimensionStrategy 사용

:macrobenchmark 모듈의 defaultConfig에서 missingDimensionStrategy를 지정하면 이 버전 차원으로 대체하도록 빌드 시스템에 지시하는 것입니다. 모듈에서 차원을 찾을 수 없는 경우 어느 차원을 사용할지 지정해야 합니다. 다음 예에서는 production 버전을 기본 차원으로 사용합니다.

Groovy

defaultConfig {
    missingDimensionStrategy "environment", "production"
}

Kotlin

defaultConfig {
    missingDimensionStrategy("environment", "production")
}

이렇게 하면 :macrobenchmark 모듈이 지정된 제품 버전만 빌드하고 벤치마킹할 수 있습니다. 이는 하나의 제품 버전에만 벤치마킹할 올바른 구성이 있는 경우에 유용합니다.

:macrobenchmark 모듈에서 제품 버전 정의

다른 제품 버전을 빌드하고 벤치마킹하려면 :macrobenchmark 모듈에서 제품 버전을 정의해야 합니다. :app 모듈에서와 마찬가지로 지정하되 dimensionproductFlavors만 할당합니다. 다른 설정은 필요하지 않습니다.

Groovy

flavorDimensions 'environment'
productFlavors {
    demo {
        dimension 'environment'
    }

    production {
        dimension 'environment'
    }
}

Kotlin

flavorDimensions += "environment"
productFlavors {
    create("demo") {
        dimension = "environment"
    }
    create("production") {
        dimension = "environment"
    }
}

프로젝트를 정의하고 동기화한 후에는 Build Variants 창에서 원하는 빌드 변형을 선택합니다.

제품 버전이 있는 프로젝트의 벤치마크 변형에서 productionBenchmark 및 출시 버전이 선택되어 있음

자세한 내용은 변형 매칭과 관련된 빌드 오류 해결을 참고하세요.

Macrobenchmark 클래스 만들기

벤치마크 테스트는 Macrobenchmark 라이브러리의 MacrobenchmarkRule JUnit4 규칙 API를 통해 제공됩니다. 이 API에는 타겟 애플리케이션이 실행되고 벤치마크되어야 하는 다양한 조건을 지정할 수 있는 measureRepeated 메서드가 포함되어 있습니다.

개발자가 지정해야 하는 항목은 타겟 애플리케이션의 packageName, 측정할 metrics, 벤치마크가 실행되어야 하는 iterations 횟수입니다.

Kotlin

@LargeTest
@RunWith(AndroidJUnit4::class)
class SampleStartupBenchmark {
    @get:Rule
    val benchmarkRule = MacrobenchmarkRule()

    @Test
    fun startup() = benchmarkRule.measureRepeated(
        packageName = TARGET_PACKAGE,
        metrics = listOf(StartupTimingMetric()),
        iterations = DEFAULT_ITERATIONS,
        setupBlock = {
            // Press home button before each run to ensure the starting activity isn't visible.
            pressHome()
        }
    ) {
        // starts default launch activity
        startActivityAndWait()
    }
}

자바

@LargeTest
@RunWith(AndroidJUnit4.class)
public class SampleStartupBenchmark {
    @Rule
    public MacrobenchmarkRule benchmarkRule = new MacrobenchmarkRule();

    @Test
    public void startup() {
        benchmarkRule.measureRepeated(
            /* packageName */ TARGET_PACKAGE,
            /* metrics */ Arrays.asList(new StartupTimingMetric()),
            /* iterations */ 5,
            /* measureBlock */ scope -> {
                // starts default launch activity
                scope.startActivityAndWait();
                return Unit.INSTANCE;
            }
        );
    }
}

벤치마크 맞춤설정 방법에 관한 모든 옵션은 벤치마크 맞춤설정 섹션을 참고하세요.

벤치마크 실행

Android 스튜디오 내에서 테스트를 실행하여 기기에서 앱 성능을 측정합니다. 다음 이미지에서 보는 것처럼 테스트 클래스 또는 메서드 옆의 여백 작업을 사용하여 다른 @Test를 실행하는 것과 동일하게 벤치마크를 실행할 수 있습니다.

테스트 클래스 옆의 여백 작업으로 Macrobenchmark 실행

다음과 같이 connectedCheck 명령어를 실행하여 명령줄에서 Gradle 모듈의 모든 벤치마크를 실행할 수도 있습니다.

./gradlew :macrobenchmark:connectedCheck

또는 다음과 같이 단일 테스트를 실행할 수 있습니다.

./gradlew :macrobenchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.macrobenchmark.startup.SampleStartupBenchmark#startup

지속적 통합으로 벤치마크를 실행하고 모니터링하는 방법에 관한 자세한 내용은 CI의 벤치마킹 섹션을 참고하세요.

벤치마크 결과

벤치마크 실행이 완료되면 측정항목이 Android 스튜디오에 직접 표시되고 CI 사용을 위해 JSON 파일로 출력됩니다. 측정된 반복마다 별개의 시스템 트레이스가 캡처됩니다. 다음 이미지와 같이 Test Results 창에 있는 링크 중 하나를 클릭하여 이러한 결과 트레이스를 열 수 있습니다.

Macrobenchmark 시작 결과

트레이스가 로드되면 분석할 프로세스를 선택하라는 메시지가 Android 스튜디오에 표시됩니다. 선택 항목은 타겟 앱 프로세스로 자동 입력됩니다.

스튜디오 트레이스 프로세스 선택

트레이스 파일이 로드되면 스튜디오의 CPU 프로파일러 도구에 결과가 표시됩니다.

스튜디오 트레이스

JSON 보고서와 모든 프로파일링 트레이스도 기기에서 호스트로 자동 복사됩니다. 이러한 보고서는 다음의 호스트 머신에 작성됩니다.

project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/

수동으로 트레이스 파일에 액세스

Perfetto 도구를 사용하여 트레이스 파일을 분석하려면 추가 단계가 필요합니다. Perfetto는 트레이스 중에 기기에서 발생한 모든 프로세스를 검사하는 반면, Android 스튜디오의 CPU 프로파일러는 검사를 단일 프로세스로 제한합니다.

Android 스튜디오 또는 Gradle 명령줄을 사용하여 테스트를 호출하면 트레이스 파일이 기기에서 호스트로 자동 복사됩니다. 이러한 보고서는 호스트 머신의 다음 위치에 작성됩니다.

project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/TrivialStartupBenchmark_startup[mode=COLD]_iter002.perfetto-trace

호스트 시스템에 트레이스 파일이 있으면 Android 스튜디오 메뉴에서 File > Open을 선택하여 열 수 있습니다. 그러면 이전 섹션에 표시된 프로파일러 도구 뷰가 표시됩니다.

구성 오류

앱이 잘못 구성(디버그 가능 또는 프로파일링 불가)되면 Macrobenchmark는 부정확하거나 불완전한 측정을 보고하는 대신 오류를 반환합니다. androidx.benchmark.suppressErrors 인수를 사용하여 이러한 오류를 억제할 수 있습니다.

에뮬레이터를 측정하려고 하거나 기기에 배터리가 부족한 경우에도 코어 가용성 및 클록 속도가 저하될 수 있기 때문에 오류가 발생합니다.

벤치마크 맞춤설정

measureRepeated 함수는 라이브러리가 수집하는 측정항목, 애플리케이션 시작 및 컴파일 방식 또는 벤치마크가 실행되는 반복 횟수에 영향을 미치는 다양한 매개변수를 허용합니다.

측정항목 캡처

측정항목은 벤치마크에서 추출된 기본 정보 유형입니다. 사용 가능한 옵션은 StartupTimingMetric, FrameTimingMetric, TraceSectionMetric입니다. 이들에 대한 자세한 내용은 측정항목 캡처 페이지를 참고하세요.

맞춤 이벤트로 트레이스 데이터 개선

맞춤 트레이스 이벤트로 애플리케이션을 계측하는 것이 유용할 수 있습니다. 트레이스 보고서의 나머지 부분에 표시되는 맞춤 트레이스 이벤트는 앱의 특정 문제를 파악하는 데 도움이 될 수 있습니다. 맞춤 트레이스 이벤트의 생성 방법에 관한 자세한 내용은 맞춤 이벤트 정의 가이드를 참고하세요.

CompilationMode

Macrobenchmark는 CompilationMode를 지정할 수 있습니다. 이 값은 DEX 바이트 코드(APK 내 바이트 코드 형식)에서 기계어 코드(사전 컴파일된 C++와 유사)로 미리 컴파일되어야 하는 앱의 양을 정의합니다.

기본적으로 Macrobenchmark는 Android 7(API 수준 24) 이상에 기준 프로필(사용 가능한 경우)을 설치하는 CompilationMode.DEFAULT로 실행됩니다. Android 6(API 수준 23) 이하를 사용 중인 경우 컴파일 모드는 APK를 기본 시스템 동작으로 완전히 컴파일합니다.

타겟 애플리케이션에 기준 프로필과 ProfileInstaller 라이브러리가 모두 포함되어 있다면 기준 프로필을 설치할 수 있습니다.

Android 7 이상에서는 CompilationMode를 맞춤설정하여 다양한 수준의 AOT(Ahead-Of-Time) 컴파일 또는 JIT 캐싱을 모방하도록 기기 내 사전 컴파일 양에 영향을 줄 수 있습니다. CompilationMode.Full, CompilationMode.Partial, CompilationMode.None을 참고하세요.

이 기능은 ART 컴파일 명령어를 기반으로 빌드됩니다. 각 벤치마크는 벤치마크 간의 간섭을 방지하기 위해 벤치마크가 시작하기 전에 프로필 데이터를 삭제합니다.

StartupMode

활동 시작을 실행하려면 미리 정의된 시작 모드(COLD, WARM 또는 HOT 중 하나)를 전달하면 됩니다. 이 매개변수는 활동 시작 방식과 테스트 시작 시의 프로세스 상태를 변경합니다.

시작 유형에 관한 자세한 내용은 Android vitals 시작 문서를 참고하세요.

샘플

샘플 프로젝트는 GitHub에서 android/performance-samples 저장소의 일부로 사용할 수 있습니다.

의견 보내기

Jetpack Macrobenchmark에 관한 문제를 보고하거나 기능 요청을 제출하려면 공개 Issue Tracker를 참고하세요.