Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ local.properties
# Log/OS Files
*.log

# Claude
.claude/

# Android Studio generated files and folders
captures/
.externalNativeBuild/
Expand Down
2 changes: 2 additions & 0 deletions _typos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ extend-exclude = [
"**/fixtures/*",
"react-native/cpp/generated/*",
"react-native/src/generated/*",
"android/**/src/main/generated/**/baseline-prof.txt",
"android/**/src/release/generated/**/baseline-prof.txt"
]
22 changes: 22 additions & 0 deletions android/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,28 @@ graphhopperApiKey=YOUR-API-KEY
We use Paparazzi for UI snapshot testing.
To update the snapshots, run `./gradlew recordPaparazziDebug`.

## Baseline Profiles

The `baselineprofile` module generates baseline profiles for the `demo-app` to improve startup and runtime performance.

To verify the build compiles:

```shell
./gradlew :demo-app:assembleBenchmark
```

To generate baseline profiles (requires a connected device or emulator):

```shell
./gradlew :demo-app:generateBaselineProfile
```

Or use the convenience script from the android directory:

```shell
./scripts/baseline_profiler/generate_baseline_profiler.sh
```

## Testing locally in a separate project

* Bump the version number to a `SNAPSHOT` in `build.gradle`.
Expand Down
56 changes: 56 additions & 0 deletions android/baselineprofile/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
plugins {
alias libs.plugins.androidTest
alias libs.plugins.baselineprofile
}

android {
namespace 'com.stadiamaps.ferrostar.baselineprofile'
compileSdk = 36

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

defaultConfig {
minSdk 28
targetSdk 35

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

targetProjectPath = ":demo-app"
testOptions {
managedDevices {
allDevices {
pixel6Api31(com.android.build.api.dsl.ManagedVirtualDevice) {
device = "Pixel 6"
apiLevel = 31
systemImageSource = "aosp"
}
}
}
}
}

baselineProfile {
managedDevices += "pixel6Api31"
useConnectedDevices = false
}

dependencies {
implementation libs.androidx.test.junit
implementation libs.androidx.test.espresso
implementation libs.androidx.uiautomator
implementation libs.androidx.benchmark.macro.junit4
}

androidComponents {
onVariants(selector().all()) { v ->
def artifactsLoader = v.artifacts.getBuiltArtifactsLoader()
v.instrumentationRunnerArguments.put(
"targetAppId",
v.testedApks.map { artifactsLoader.load(it)?.applicationId }
)
}
}
3 changes: 3 additions & 0 deletions android/baselineprofile/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.stadiamaps.ferrostar.baselineprofile

import androidx.benchmark.macro.junit4.BaselineProfileRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
@LargeTest
class BaselineProfileGenerator {

@get:Rule
val rule = BaselineProfileRule()

@Test
fun generate() {
rule.collect(
packageName = "com.stadiamaps.ferrostar.demo",
) {
pressHome()
startActivityAndWait()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.stadiamaps.ferrostar.baselineprofile

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 androidx.test.filters.LargeTest
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
@LargeTest
class StartupBenchmarks {

@get:Rule
val rule = MacrobenchmarkRule()

@Test
fun startupCompilationNone() = benchmark(CompilationMode.None())

@Test
fun startupCompilationBaselineProfiles() =
benchmark(CompilationMode.Partial(BaselineProfileMode.Require))

private fun benchmark(compilationMode: CompilationMode) {
rule.measureRepeated(
packageName = "com.stadiamaps.ferrostar.demo",
metrics = listOf(StartupTimingMetric()),
compilationMode = compilationMode,
startupMode = StartupMode.COLD,
iterations = 10,
) {
pressHome()
startActivityAndWait()
}
}
}
2 changes: 2 additions & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ plugins {
alias libs.plugins.compose.compiler apply false
alias libs.plugins.mavenPublish apply false
alias libs.plugins.kotlinSerialization apply false
alias libs.plugins.androidTest apply false
alias libs.plugins.baselineprofile apply false
}

// Gradle 9 removed `Project.exec(Closure)`; some third-party plugins still call it.
Expand Down
9 changes: 9 additions & 0 deletions android/core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ plugins {
alias libs.plugins.ktfmt
alias libs.plugins.mavenPublish
alias libs.plugins.kotlinSerialization
alias libs.plugins.baselineprofile
}

android {
Expand Down Expand Up @@ -60,6 +61,8 @@ dependencies {
//noinspection UseTomlInstead
implementation 'net.java.dev.jna:jna:5.17.0@aar'

baselineProfile(project(":baselineprofile"))

testImplementation libs.junit
testImplementation libs.kotlinx.coroutines.test
testImplementation libs.mockk
Expand Down Expand Up @@ -110,6 +113,12 @@ android.libraryVariants.all { variant ->
// idea.module.generatedSourceDirs += file("${buildDir}/generated/source/uniffi/${variant.name}/java/uniffi")
}

baselineProfile {
filter {
include "com.stadiamaps.ferrostar.core.**"
}
}

mavenPublishing {
publishToMavenCentral()
if (!project.hasProperty(SKIP_SIGNING_PROPERTY)) {
Expand Down
Loading
Loading