#Banchmark Android Developer 공식문서
=>https://developer.android.com/studio/profile/benchmark?hl=ko
#Android Developers Youtube 링크
=>https://www.youtube.com/watch?v=Z96wfbID_Yc
-항목을 스크롤하여 클릭하는 등의 세부화면이 표시 될 때 얼마나 많은 프레임이 삭제되었는지 측정하면 모든 항목이 얼마나 빠른지 등등의 앱의 성능을 측정할 수 있고 , 측정을 자동화 할 수 있다. 무조건 수동으로 측정할 필요는 없고 항상 스크립트를 작성할 필요도 없다. 따라서 Banchmark를 사용하여 앱의 성능을 측정한 후 성능을 향상 시키려는 시도를 할 수 있다.
-Android를 Project에서 보는 것으로 변경 한 후 New->Module을 클릭하면 아래와 같은 창이 뜨는데 , 아래 창에서 Benchmark를 클릭한 후 해당 화면에 아래 사진처럼 입력하면 된다. 이때 선택 할 수 있는 Benchmark의 종류는 Macrobenchmark Microbenchmark 이렇게 두개가 존재한다.
-AndroidManifest.xml 파일의 application 태그 내부에 Benchmark 관련 설정을 진행해준다.
<profileable
android:shell="true"
tools:targetApi="34" />
-Benchmark로 성능을 테스트 할 모듈에서 New -> File을 클릭 한 후 "benchmark-rules.pro"라는 파일을 만든 후 "-dontobfuscate"를 작성해준다.
-Benchmark의 모듈의 build.gradle에 가서 buildTypes 내부의 benchmark 내부에 "proguardFiles("benchmark-rules.pro")"를 추가해준다.
buildTypes {
create("benchmark") {
isDebuggable = true
signingConfig = getByName("debug").signingConfig
matchingFallbacks += listOf("release")
proguardFiles("benchmark-rules.pro")
}
}
-Benchmark로 성능을 측정할 모듈의 빌드를 변형하기 위해서 Build -> Select Build Variant 를 순서대로 클릭 하면 아래와 같은 화면이 뜰 것이다.
-이때 성능을 측정할 모듈의 빌드를 "benchmark"로 변경해주어야 한다.
-성능을 측정할 모듈의 build.gradle에 아래와 같은 종속성을 추가해준다.
implementation("androidx.profileinstaller:profileinstaller:${version_profileinstaller}")
implementation("androidx.benchmark:benchmark-macro:1.2.3")
-기본적으로 작성되어져있는 코드 사용해서 앱의 시작 시간을 측정해 볼 수 있다.
@RunWith(AndroidJUnit4::class)
class ExampleStartupBenchmark {
@get:Rule
val benchmarkRule = MacrobenchmarkRule()
@Test
fun startup() = benchmarkRule.measureRepeated(
packageName = "com.company.velogbanchmark",
metrics = listOf(StartupTimingMetric()),
iterations = 5,
startupMode = StartupMode.COLD
) {
pressHome()
startActivityAndWait()
}
}
-위 코드 설명
@RunWith(AndroidJUnit4::class) : 해당 클래스가 AnroidJUnit4 테스트 러너를 사용하여 테스트를 실행한다는 것을 알려준다.
@get:Rule : JUnit 테스트 규칙을 선언하는 어노테이션으로서 테스트 메서드가 실행되기 전에 어노테이션이 달린 코드를 수행하도록 한다.
val benchmarkRule = MacrobenchmarkRule() : MacrobenchmarkRule()을 통해서 MacrobenchmarkRule 객체를 생성한다. 이는 Benchmark 테스트에 필요한 환경을 설정한다.
@Test : 해당 함수가 테스트 케이스임을 알리는 어노테이션으로서 해당 어노테이션이 달린 메서드를 통해 Benchmark를 수행한다.
fun startup() : Benchmark를 수행할 메서드의 이름이다.
benchmarkRule.measureRepeated() : Benchmarking을 반복적으로 수행하고 결과를 측정한다.
packageName = "com.company.velogbanchmark : Benchmark를 수행할 앱의 패키지 이름
metrics = listOf(StartupTimingMetric()) : 벤치마크를 수행 할 때 측정할 성능의 지표를 나타내는 역할을 한다. StartupTimingMetric()를 작성하였으므로 여기서는 성능의 지표로 시간을 활용한다.
iterations = 5 : 벤치마크를 몇번 수행 할 것인지를 알려준다.
startupMode = StartupMode.COLD : COLD(앱이 완전히 종료된 상태에서 시작) /
위 코드를 실행하면 아래와 같은 결과가 나온다. 아래 사진은 앱의 시작시간을 Benchmark한 결과표이다. (주의!!반드시 실제 기기에서 진행해야한다.)
fun MacrobenchmarkScope.addElementsAndScrollDown() {
val button = device.findObject(By.text("Click me"))
val list = device.findObject(By.res("item_list"))
repeat(30) {
button.click()
}
device.waitForIdle()
list.setGestureMargin(device.displayWidth / 5)
list.fling(Direction.DOWN)
device.findObject(By.text("Element 29")).click()
device.wait(Until.hasObject(By.text("Detail: Element 29")), 5000)
}
-위 함수 설명
-그럼 아래와 같은 결과가 나오게 된다.
-StartupTimingMetric()는 앱의 시작 시간을 측정한다.
-FrameTimingMetric()는 앱의 프레임 렌더링 시간을 측정한다.
-AudioUnderrunMetric()는 앱이 오디오 끊김 현상을 측정한다.
-TraceMetric()는 앱의 이벤트를 추적하여 시간을 측정한다.
-PowerMetric()는 앱의 배터리 소모량을 측정한다.
-MemoryCountersMetric()는 앱의 세부적인 메모리 사용량을 측정한다.
-MemoryUsageMetric()는 앱의 전반적인 메모리 사용량을 측정한다.
-StartupMode.COLD는 앱이 완전히 종료되고 다시 시작되는 것을 의미한다.
-StartupMode.WARM은 앱의 프로세스가 백그라운드에서 실행중이지만 액티비티는 아직 생성되지 않은 상태에서 시작하는 것을 의미한다. 즉, 최근 앱 목록에서 앱을 선택하여 다시 시작하는 것을 의미한다. 그러니가 홈화면의 왼쪽 버튼을 누르면 자주 사용하는 앱 4개가 뜨는데 거기서 앱을 시작하는 것을 의미한다.
-StartupMode.HOT는 앱이 백그라운드에서 이미 실행 중이고 모든 액티비티 스택이 메모리에 존재할 때 시작하는 것을 의미한다. 즉, 사용자가 다른 앱을 사용하다가 이전에 사용하던 앱으로 돌아가는 것을 의미한다. 그러니까 홈 버튼 왼쪽에 있는 것을 통해서 실행중이던 앱들중 하나를 선택하여 앱을 시작하는 것을 의미하는 것이다.
-startActivityAndWait() : 앱을 실행하고 대기
-By.text() : 객체를 식별하기 위한 조건을 text 기준으로 제시한다.
-By.res("resourceName") : 객체를 식별하기 위한 조건을 "resourceName"을 기준으로 제시한다. 이때 해당 객체에 .testTag("tag")를 붙혀서 resourceName과 tag가 같은 객체를 찾는 것이다.
-device.findObject : 화면에서 특정 객체를 찾는다.
-.click() : 해당 객체를 클릭한다.
-.wait(작업 , timeout) : 파라미터의 작업이 timeout만큼 끝날때까지 기다린다.
-setGestureMargin() : 제스처(스와이프 또는 터치)할 때 여백을 지정한다.
-fling() : 파라미터의 방향으로 스크롤을 한다.