Android: Baseline profile generation
This creates a new benchmark module that is responsible for generating baseline profiles and testing them. As part of this commit a baseline-prof.txt file has been included to speed up launch times with the app in its current state. Later, profile generation can be automated and keep up with the app as it changes.
This commit is contained in:
parent
61c10a5644
commit
974003888a
|
@ -33,6 +33,8 @@ android {
|
|||
versionCode(getBuildVersionCode())
|
||||
|
||||
versionName "${getVersion()}"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
|
@ -69,6 +71,19 @@ android {
|
|||
versionNameSuffix '-debug'
|
||||
jniDebuggable true
|
||||
}
|
||||
|
||||
benchmark {
|
||||
signingConfig signingConfigs.debug
|
||||
matchingFallbacks = ['release']
|
||||
debuggable false
|
||||
applicationIdSuffix ".benchmark"
|
||||
versionNameSuffix '-benchmark'
|
||||
proguardFiles getDefaultProguardFile(
|
||||
'proguard-android-optimize.txt'),
|
||||
'proguard-rules.pro'
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
|
@ -107,6 +122,7 @@ dependencies {
|
|||
implementation 'com.google.android.material:material:1.7.0'
|
||||
implementation 'androidx.core:core-splashscreen:1.0.0'
|
||||
implementation 'androidx.preference:preference:1.2.0'
|
||||
implementation 'androidx.profileinstaller:profileinstaller:1.2.1'
|
||||
|
||||
// Force dependency version to solve build conflict with androidx preferences
|
||||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.touchscreen"
|
||||
|
@ -44,6 +45,9 @@
|
|||
<meta-data
|
||||
android:name="android.max_aspect"
|
||||
android:value="2.1"/>
|
||||
<profileable
|
||||
android:shell="true"
|
||||
tools:targetApi="29" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.main.MainActivity"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1 @@
|
|||
/build
|
|
@ -0,0 +1,73 @@
|
|||
import com.android.build.api.dsl.ManagedVirtualDevice
|
||||
|
||||
plugins {
|
||||
id 'com.android.test'
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'com.dolphin.benchmark'
|
||||
compileSdk 33
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdk 23
|
||||
targetSdk 33
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
testOptions {
|
||||
managedDevices {
|
||||
devices {
|
||||
pixel2Api31 (ManagedVirtualDevice) {
|
||||
device = "Pixel 2"
|
||||
apiLevel = 31
|
||||
systemImageSource = "aosp"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
// This benchmark buildType is used for benchmarking, and should function like your
|
||||
// release build (for example, with minification on). It's signed with a debug key
|
||||
// for easy local/CI testing.
|
||||
benchmark {
|
||||
signingConfig signingConfigs.debug
|
||||
matchingFallbacks = ['release']
|
||||
debuggable true
|
||||
applicationIdSuffix ".benchmark"
|
||||
versionNameSuffix '-benchmark'
|
||||
proguardFiles getDefaultProguardFile(
|
||||
'proguard-android-optimize.txt'),
|
||||
'proguard-rules.pro'
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
}
|
||||
}
|
||||
|
||||
targetProjectPath = ":app"
|
||||
experimentalProperties["android.experimental.self-instrumenting"] = true
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'androidx.test.ext:junit:1.1.4'
|
||||
implementation 'androidx.test.espresso:espresso-core:3.5.0'
|
||||
implementation 'androidx.test.uiautomator:uiautomator:2.2.0'
|
||||
implementation 'androidx.benchmark:benchmark-macro-junit4:1.1.1'
|
||||
}
|
||||
|
||||
androidComponents {
|
||||
beforeVariants(selector().all()) {
|
||||
enabled = buildType == "benchmark"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<queries>
|
||||
<package android:name="org.dolphinemu.dolphinemu.debug" />
|
||||
</queries>
|
||||
</manifest>
|
|
@ -0,0 +1,43 @@
|
|||
package com.dolphin.benchmark
|
||||
|
||||
import androidx.benchmark.macro.ExperimentalBaselineProfilesApi
|
||||
import androidx.benchmark.macro.junit4.BaselineProfileRule
|
||||
import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner
|
||||
import androidx.test.uiautomator.UiSelector
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@OptIn(ExperimentalBaselineProfilesApi::class)
|
||||
@RunWith(AndroidJUnit4ClassRunner::class)
|
||||
class BaselineProfileGenerator {
|
||||
|
||||
@get:Rule
|
||||
val rule = BaselineProfileRule()
|
||||
|
||||
@Test
|
||||
fun generate() = rule.collectBaselineProfile(
|
||||
packageName = "org.dolphinemu.dolphinemu.benchmark",
|
||||
profileBlock = {
|
||||
pressHome()
|
||||
startActivityAndWait()
|
||||
|
||||
// Dismiss analytics dialog due to issue with finding button
|
||||
device.pressBack()
|
||||
|
||||
// Navigate through activities that don't require games
|
||||
// TODO: Make all activities testable without having games available
|
||||
// TODO: Use resource strings to support more languages
|
||||
|
||||
// Navigate to the Settings Activity
|
||||
val settings = device.findObject(UiSelector().description("Settings"))
|
||||
settings.clickAndWaitForNewWindow(30_000)
|
||||
|
||||
// Go through settings and to the User Data Activity
|
||||
val config = device.findObject(UiSelector().textContains("Config"))
|
||||
config.click()
|
||||
val userData = device.findObject(UiSelector().textContains("User Data"))
|
||||
userData.clickAndWaitForNewWindow(30_000)
|
||||
},
|
||||
)
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.dolphin.benchmark
|
||||
|
||||
import androidx.benchmark.macro.BaselineProfileMode
|
||||
import androidx.benchmark.macro.CompilationMode
|
||||
import androidx.benchmark.macro.StartupMode
|
||||
import androidx.benchmark.macro.StartupTimingMetric
|
||||
import androidx.benchmark.macro.junit4.MacrobenchmarkRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class StartupBenchmark {
|
||||
@get:Rule
|
||||
val benchmarkRule = MacrobenchmarkRule()
|
||||
|
||||
@Test
|
||||
fun startupBaselineProfileDisabled() = startup(
|
||||
CompilationMode.Partial(baselineProfileMode = BaselineProfileMode.Disable, warmupIterations = 1)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun startupBaselineProfile() = startup(
|
||||
CompilationMode.Partial(baselineProfileMode = BaselineProfileMode.Require, warmupIterations = 1)
|
||||
)
|
||||
|
||||
private fun startup(compilationMode: CompilationMode) = benchmarkRule.measureRepeated(
|
||||
packageName = "org.dolphinemu.dolphinemu.benchmark",
|
||||
metrics = listOf(StartupTimingMetric()),
|
||||
iterations = 10,
|
||||
compilationMode = compilationMode,
|
||||
startupMode = StartupMode.COLD,
|
||||
setupBlock = {
|
||||
pressHome()
|
||||
}
|
||||
) {
|
||||
startActivityAndWait()
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ buildscript {
|
|||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.3.1'
|
||||
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.20'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
include ':app'
|
||||
include ':benchmark'
|
||||
|
|
Loading…
Reference in New Issue