[안드로이드스튜디오_문화][Benchmark]

기말 지하기포·2023년 12월 14일
1

#Banchmark Android Developer 공식문서
=>https://developer.android.com/studio/profile/benchmark?hl=ko

#Android Developers Youtube 링크
=>https://www.youtube.com/watch?v=Z96wfbID_Yc

Banchmark 기능

-항목을 스크롤하여 클릭하는 등의 세부화면이 표시 될 때 얼마나 많은 프레임이 삭제되었는지 측정하면 모든 항목이 얼마나 빠른지 등등의 앱의 성능을 측정할 수 있고 , 측정을 자동화 할 수 있다. 무조건 수동으로 측정할 필요는 없고 항상 스크립트를 작성할 필요도 없다. 따라서 Banchmark를 사용하여 앱의 성능을 측정한 후 성능을 향상 시키려는 시도를 할 수 있다.

Benchmark 초기 설정

1 Benchmark 모듈 생성

-Android를 Project에서 보는 것으로 변경 한 후 New->Module을 클릭하면 아래와 같은 창이 뜨는데 , 아래 창에서 Benchmark를 클릭한 후 해당 화면에 아래 사진처럼 입력하면 된다. 이때 선택 할 수 있는 Benchmark의 종류는 Macrobenchmark Microbenchmark 이렇게 두개가 존재한다.

  • Target application : 성능 확인 할 모듈 이름
  • Module name : 내가 만들 Benchmark 모듈 이름

  • Macrobenchmark
  • 넓은 범위 코드의 성능을 측정
  • 전체 앱의 성능(ex: 앱의 시작 시간 , 화면 스크롤 시간..등등)을 측정하는데 사용된다.

  • Microbenchmark
  • 작은 범위 코드의 성능을 측정
  • 메모리할당 , 함수 호출 시간 , 작은 반복 루프의 성능등을 측정하는데 사용된다.

2 AndroidManifest 파일 설정

-AndroidManifest.xml 파일의 application 태그 내부에 Benchmark 관련 설정을 진행해준다.

<profileable
	android:shell="true"
	tools:targetApi="34" />
  • android : shell => 앱이 쉘 명령을 통해 시작될 때 프로파일링을 수행하는 것을 허용
  • tools : targetApi => targetApi 이상에서만 적용됨을 알려준다.

3 benchmark-rules.pro 생성

-Benchmark로 성능을 테스트 할 모듈에서 New -> File을 클릭 한 후 "benchmark-rules.pro"라는 파일을 만든 후 "-dontobfuscate"를 작성해준다.

4 buildTypes 추가

-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")
	}
}

5 빌드 변경

-Benchmark로 성능을 측정할 모듈의 빌드를 변형하기 위해서 Build -> Select Build Variant 를 순서대로 클릭 하면 아래와 같은 화면이 뜰 것이다.

-이때 성능을 측정할 모듈의 빌드를 "benchmark"로 변경해주어야 한다.

6 종속성 추가

-성능을 측정할 모듈의 build.gradle에 아래와 같은 종속성을 추가해준다.

implementation("androidx.profileinstaller:profileinstaller:${version_profileinstaller}")

implementation("androidx.benchmark:benchmark-macro:1.2.3")

7 테스트 코드

-기본적으로 작성되어져있는 코드 사용해서 앱의 시작 시간을 측정해 볼 수 있다.

@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()
    }
}
  • 위와 같이 ExampleStartupBenchmark라는 클래스가 생길 텐데 위 코드는 앱의 시작 시간을 측정하는 코드이다.

-위 코드 설명

  • @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)
}
  • 위의 코드는 스크로하면서 프레임 렌더링 시간을 측정하는 예시코드이다. 위 코드처럼 앱의 동작중에서 내가 원하는 동작을 발생시켜서 해당 동작에 대한 성능 측정을 하기 위해서는 여러 단계를 거쳐야한다. Pyautogui에서 자동화하는 것처럼 앱의 동작과정을 코딩으로 Benchmark에게 알려주면 Benchmark는 해당 동작을 스스로 구현해내면서 해당 동작의 성능을 측정한다.

-위 함수 설명

  • MacrobenchmarkScope의 확장 함수로서 생성해야 한다. 왜냐하면 benchmarkRule.measureRepeated() 후행 람다식안에 해당 함수가 들어가야 하는데 해당 람다식이 MacrobanchmarkScope 이기 때문이다.
  • device.findObject : 화면에서 특정 객체를 찾는 메서드이다.
  • By.text() : 객체를 식별하기 위한 조건을 text 기준으로 제시한다.
  • By.res("resourceName") : 객체를 식별하기 위한 조건을 "resourceName"을 기준으로 제시한다. 이때 해당 객체에 .testTag("tag")를 붙혀서 resourceName과 tag가 같은 객체를 찾는 것이다.
  • device.waitForIdle() : 디바이스에서 해당 동작을 완료할때까지 대기하게 한다.
  • list.setGestureMargin() : 한번 스크롤 할 때 범위를 지정한다.
  • list.fling(방향) : 스크롤 방향을 지정한다.
  • .click() : 해당 객체를 클릭한다
  • .wait(작업 , timeout) : 파라미터의 작업이 timeout만큼 끝날때까지 기다린다.

-그럼 아래와 같은 결과가 나오게 된다.

성능 지표 종류

-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() : 파라미터의 방향으로 스크롤을 한다.

profile
포기하지 말기

0개의 댓글