yayacal/macrobenchmark/build.gradle.kts

125 lines
5.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

plugins {
id("com.android.test")
}
android {
namespace = "plus.rua.project.macrobenchmark"
compileSdk = libs.versions.android.compileSdk.get().toInt()
defaultConfig {
minSdk = libs.versions.android.minSdk.get().toInt()
targetSdk = libs.versions.android.targetSdk.get().toInt()
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
// 允许在模拟器 / debuggable target 上运行 macrobenchmark仅用于开发验证
// 正式发布 benchmark 请在物理设备、release 目标应用上执行。
testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "EMULATOR,DEBUGGABLE"
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
buildTypes {
// benchmark 构建类型必须与 app 模块的 release 类型签名一致
create("benchmark") {
isDebuggable = true
signingConfig = signingConfigs.getByName("debug")
matchingFallbacks += listOf("release")
}
}
targetProjectPath = ":app"
experimentalProperties["android.experimental.self-instrumenting"] = true
}
dependencies {
implementation(libs.androidx.benchmark.macro)
implementation(libs.androidx.test.ext.junit)
implementation(libs.androidx.test.espresso)
implementation(libs.androidx.test.uiautomator)
}
// ===== Baseline Profile / Startup Profile 自动复制 =====
// 运行 ./gradlew :macrobenchmark:updateBaselineProfile 即可一键生成并复制
val updateBaselineProfile by tasks.registering {
group = "benchmark"
description = "运行 connectedBenchmarkAndroidTest 并将生成的 Baseline Profile 与 Startup Profile 复制到 :core 模块"
// 依赖基准测试 task需要先连接设备/模拟器)
dependsOn("connectedBenchmarkAndroidTest")
// 该 task 的输入是 benchmark 运行后的产物,因此不应被跳过
outputs.upToDateWhen { false }
// 预先计算目标路径,避免在 doLast 中引用 project 对象configuration cache 兼容)
val baselineTargetPath = rootProject.projectDir
.resolve("core/src/main/baseline-prof.txt")
.absolutePath
val startupTargetDirPath = rootProject.projectDir
.resolve("core/src/main/baselineProfiles")
.absolutePath
val buildDirPath = layout.buildDirectory.get().asFile.absolutePath
doLast {
val sourcePaths = listOf(
"$buildDirPath/outputs/connected_android_test_additional_output/benchmark/",
"$buildDirPath/outputs/connected_android_test_additional_output/",
)
// benchmark 1.4+ 文件名格式:{Class}_{Method}-baseline-prof.txt / {Class}_{Method}-startup-prof.txt
// 排除带时间戳的历史文件(如 ...-2026-06-15-startup-prof.txt只取当前 canonical 文件
val dateStampRegex = Regex("-\\d{4}-\\d{2}-\\d{2}-")
fun findNewestProfile(suffix: String): File? {
val candidates = sourcePaths.flatMap { path ->
val dir = File(path)
if (!dir.exists()) emptyList()
else dir.walkTopDown().filter {
it.isFile &&
it.name.endsWith(suffix) &&
!it.name.contains(dateStampRegex)
}.toList()
}
return candidates
.sortedWith(compareByDescending<File> { it.lastModified() }.thenBy { it.absolutePath })
.firstOrNull()
}
fun requireProfile(suffix: String, label: String): File {
val sourceFile = findNewestProfile(suffix)
?: throw GradleException(
"未找到生成的 *$suffix。\n" +
"请确认:\n" +
" 1. 设备/模拟器已连接 (adb devices)\n" +
" 2. 应用已安装在 benchmark 构建类型下\n" +
" 3. 检查 macrobenchmark/build/outputs/ 下是否有输出"
)
if (sourceFile.length() == 0L) {
throw GradleException("生成的 $label 文件为空: ${sourceFile.absolutePath}")
}
return sourceFile
}
// 1) 先定位并校验两份源文件,确保都可用再开始复制,避免部分覆盖目标文件
val baselineSource = requireProfile("-baseline-prof.txt", "Baseline Profile")
val startupSource = requireProfile("-startup-prof.txt", "Startup Profile")
// 2) Baseline Profile → AOT 编译优化
val baselineTargetFile = File(baselineTargetPath)
baselineSource.copyTo(baselineTargetFile, overwrite = true)
logger.lifecycle("✅ Baseline Profile 已自动复制到: ${baselineTargetFile.absolutePath}")
logger.lifecycle(" 来源: ${baselineSource.absolutePath}")
// 3) Startup Profile → DEX layout 优化(必须放在 baselineProfiles/startup-prof.txt
val startupTargetDir = File(startupTargetDirPath)
startupTargetDir.mkdirs()
val startupTargetFile = File(startupTargetDir, "startup-prof.txt")
startupSource.copyTo(startupTargetFile, overwrite = true)
logger.lifecycle("✅ Startup Profile 已自动复制到: ${startupTargetFile.absolutePath}")
logger.lifecycle(" 来源: ${startupSource.absolutePath}")
}
}