지속적 통합의 벤치마크

지속적 통합(CI)에서 벤치마크를 실행하여 시간 경과에 따른 성능을 추적하고 앱이 출시되기 전에 성능 회귀(또는 개선)를 파악할 수 있습니다. 이 페이지에서는 CI의 벤치마킹에 관한 기본 정보를 제공합니다.

CI에서 벤치마킹을 시작하기 전에 결과 캡처 및 평가가 일반 테스트와 어떻게 다른지 살펴보세요.

퍼지 결과

벤치마크는 계측 테스트이지만 단순히 성공 여부만 테스트하는 것은 아닙니다. 벤치마크는 실행되는 특정 기기와 관련된 타이밍을 측정합니다. 시간 경과에 따른 결과를 그래프로 나타내면 측정 시스템의 변화를 모니터링하고 노이즈를 관찰할 수 있습니다.

실제 기기 사용

실제 Android 기기에서 벤치마크를 실행합니다. 에뮬레이터에서 실행할 수 있지만 에뮬레이터는 실제 사용자 환경을 나타내지 않고 대신 호스트 OS 및 하드웨어 기능에 연결된 숫자를 제공하므로 사용하지 않는 것이 좋습니다. 실제 기기를 사용하거나 실제 기기에서 테스트를 실행할 수 있는 Firebase Test Lab과 같은 서비스를 사용하는 것이 좋습니다.

벤치마크 실행

CI 파이프라인의 일부로 벤치마크를 실행하는 것은 Android 스튜디오에서 로컬로 벤치마크를 실행하는 것과 다를 수도 있습니다. 로컬에서는 일반적으로 단일 Gradle connectedCheck 작업으로 Android 통합 테스트를 실행합니다. 이 작업은 APK 및 테스트 APK를 자동으로 빌드하고 CI 서버에 연결된 기기에서 테스트를 실행합니다. CI에서 실행할 때는 이 흐름을 별도의 단계로 분할해야 하는 경우가 많습니다.

빌드

Microbenchmark 라이브러리의 경우 Gradle 작업 assemble[VariantName]AndroidTest를 실행합니다. 그러면 애플리케이션 코드와 테스트된 코드를 모두 포함하는 테스트 APK가 생성됩니다.

또는 Macrobenchmark 라이브러리를 사용하려면 타겟 APK와 테스트 APK를 별도로 빌드해야 합니다. 따라서 :app:assemble[VariantName]:macrobenchmark:assemble[VariantName] Gradle 작업을 실행합니다.

설치 및 실행

이 단계는 일반적으로 Gradle 작업을 실행하지 않고도 처리됩니다. 실제 기기에서 테스트를 실행할 수 있는 서비스를 사용하는지 여부에 따라 추상화될 수도 있습니다.

설치하려면 adb install 명령어를 사용하고 테스트 APK 또는 타겟 APK를 지정합니다.

adb shell am instrument 명령어를 실행하여 모든 벤치마크를 실행합니다.

adb shell am instrument -w com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner

Macrobenchmark 라이브러리를 사용할 때는 일반 androidx.test.runner.AndroidJUnitRunner를 계측 실행기로 사용하세요.

-e 인수를 사용하여 Gradle 구성과 동일한 계측 인수를 전달할 수 있습니다. 모든 계측 인수 옵션은 Macrobenchmark 계측 인수 또는 Microbenchmark의 계측 인수 추가를 참고하세요.

예를 들어 pull 요청 확인 프로세스의 일부로 Microbenchmark를 실행하도록 dryRunMode 인수를 설정할 수 있습니다. 이 플래그를 사용 설정하면 Microbenchmark가 단일 루프에서만 실행되어 제대로 실행되는지 확인할 수 있고 오랜 시간이 소요되지도 않습니다.

adb shell am instrument -w -e "androidx.benchmark.dryRunMode.enable" "true" com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner

명령줄에서 계측 테스트를 실행하는 방법에 관한 자세한 내용은 ADB로 테스트 실행을 참고하세요.

시계 잠금

Microbenchmark Gradle 플러그인은 ./gradlew lockClocks 명령어를 제공하여 루팅된 기기의 CPU 시계를 잠급니다. 이 명령어는 'userdebug' 빌드와 같이 루팅된 기기에 대한 액세스가 있을 때 안정성을 확보하는 데 유용합니다. 라이브러리 소스에서 사용 가능한 lockClocks.sh 셸 스크립트로 이 명령어를 복제할 수 있습니다.

스크립트를 Linux 또는 Mac 호스트에서 직접 실행하거나 몇 가지 adb 명령어를 사용하여 기기로 푸시할 수 있습니다.

adb push path/lockClocks.sh /data/local/tmp/lockClocks.sh
adb shell /data/local/tmp/lockClocks.sh
adb shell rm /data/local/tmp/lockClocks.sh

호스트에서 직접 셸 스크립트를 실행하면 이러한 명령어가 연결된 기기에 전달됩니다.

CPU 시계를 잠그면 도움이 되는 이유에 관한 자세한 내용을 알고 싶다면 일관된 벤치마크를 획득하는 방법을 확인하세요.

결과 수집

벤치마킹 라이브러리는 각 벤치마크 실행 후 Android 지원 기기의 디렉터리 프로파일링 트레이스와 함께 JSON으로 측정값을 출력합니다. Macrobenchmark 라이브러리는 perfetto 트레이스 파일 여러 개를 출력합니다. 각 MacrobenchmarkRule.measureRepeated 루프의 측정된 반복마다 하나씩 생기는 것입니다. 하지만 Microbenchmark는 각 BenchmarkRule.measureRepeated의 모든 반복에 관해 단일 트레이스 파일을 만듭니다. 프로파일링 트레이스 파일도 동일한 디렉터리에 출력됩니다.

파일 저장 및 찾기

Gradle을 사용하여 벤치마크를 실행하면 이러한 파일이 호스트 컴퓨터의 build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/ 아래에 있는 출력 디렉터리에 자동으로 복사됩니다.

adb 명령어를 사용하여 직접 실행하는 경우 파일을 수동으로 가져와야 합니다. 기본적으로 보고서는 기기 내, 즉 테스트된 앱의 외부 저장소 미디어 디렉터리에 저장됩니다. 편의를 위해 라이브러리는 파일의 경로를 Logcat에 출력합니다. 출력 폴더는 벤치마크를 실행하는 Android 버전에 따라 다를 수 있습니다.

Benchmark: writing results to /storage/emulated/0/Android/media/com.example.macrobenchmark/com.example.macrobenchmark-benchmarkData.json

계측 인수 additionalTestOutputDir을 사용하여 기기에서 벤치마크 보고서가 저장되는 위치를 구성할 수 있습니다. 이 폴더는 앱에서 쓰기 가능한 폴더여야 합니다.

adb shell am instrument -w -e additionalTestOutputDir /sdcard/Download/ com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner

Android 10(API 수준 29) 이상에서는 앱 테스트가 기본적으로 저장소 샌드박스에서 실행되므로 앱이 앱별 디렉터리 외부의 파일에 액세스할 수 없습니다. /sdcard/Download와 같은 전역 디렉터리에 저장하려면 다음 계측 인수를 전달하세요.

-e no-isolated-storage true

또한 벤치마크 매니페스트에서 기존 저장소 옵션도 명시적으로 허용해야 합니다.

<application android:requestLegacyExternalStorage="true" ... >

자세한 내용은 범위 지정 저장소를 일시적으로 선택 해제를 참고하세요.

파일 검색

생성된 파일을 기기에서 검색하려면 지정된 파일을 호스트의 현재 디렉터리로 가져오는 adb pull 명령어를 사용하세요.

adb pull /storage/emulated/0/Android/media/com.example.macrobenchmark/com.example.macrobenchmark-benchmarkData.json

지정된 폴더에서 모든 benchmarkData를 검색하려면 다음 스니펫을 확인합니다.

# The following command pulls all files ending in -benchmarkData.json from the directory
# hierarchy starting at the root /storage/emulated/0/Android.
adb shell find /sdcard/Download -name "*-benchmarkData.json" | tr -d '\r' | xargs -n1 adb pull

트레이스 파일(.trace 또는 .perfetto-trace)은 benchmarkData.json과 동일한 폴더에 저장되므로 동일한 방식으로 수집할 수 있습니다.

벤치마크 데이터 예

벤치마크 라이브러리는 벤치마크를 실행한 기기 및 실행한 실제 벤치마크에 관한 정보가 포함된 JSON 파일을 생성합니다. 다음 스니펫은 생성된 JSON 파일을 나타냅니다.

{
    "context": {
        "build": {
            "brand": "google",
            "device": "blueline",
            "fingerprint": "google/blueline/blueline:12/SP1A.210812.015/7679548:user/release-keys",
            "model": "Pixel 3",
            "version": {
                "sdk": 31
            }
        },
        "cpuCoreCount": 8,
        "cpuLocked": false,
        "cpuMaxFreqHz": 2803200000,
        "memTotalBytes": 3753299968,
        "sustainedPerformanceModeEnabled": false
    },
    "benchmarks": [
        {
            "name": "startup",
            "params": {},
            "className": "com.example.macrobenchmark.startup.SampleStartupBenchmark",
            "totalRunTimeNs": 4975598256,
            "metrics": {
                "timeToInitialDisplayMs": {
                    "minimum": 347.881076,
                    "maximum": 347.881076,
                    "median": 347.881076,
                    "runs": [
                        347.881076
                    ]
                }
            },
            "sampledMetrics": {},
            "warmupIterations": 0,
            "repeatIterations": 3,
            "thermalThrottleSleepSeconds": 0
        }
    ]
}

추가 리소스