1. ก่อนเริ่มต้น
Codelab นี้แสดงวิธีสร้าง Baseline Profile เพื่อเพิ่มประสิทธิภาพของแอปพลิเคชัน และวิธีตรวจสอบประโยชน์ด้านประสิทธิภาพของการใช้ Baseline Profile
สิ่งที่คุณต้องมี
- Android Studio Hedgehog (2023.1.1) ขึ้นไป
- ปลั๊กอิน Android Gradle 8.0 ขึ้นไป
- ความเข้าใจพื้นฐานเกี่ยวกับ Jetpack Macrobenchmark
- อุปกรณ์ Android จริงที่ใช้ Android 7 (API ระดับ 24) ขึ้นไป
สิ่งที่คุณต้องดำเนินการ
- ตั้งค่าโปรเจ็กต์เพื่อใช้เครื่องมือสร้าง Baseline Profiles
- สร้างโปรไฟล์พื้นฐานเพื่อเพิ่มประสิทธิภาพการเริ่มต้นแอปและประสิทธิภาพการเลื่อน
- ยืนยันการเพิ่มประสิทธิภาพด้วยไลบรารี Jetpack Macrobenchmark
สิ่งที่คุณจะได้เรียนรู้
- โปรไฟล์พื้นฐานและวิธีที่โปรไฟล์เหล่านี้ช่วยปรับปรุงประสิทธิภาพของแอป
- วิธีสร้างโปรไฟล์พื้นฐาน
- การเพิ่มประสิทธิภาพของโปรไฟล์พื้นฐาน
2. การเริ่มตั้งค่า
หากต้องการเริ่มต้นใช้งาน ให้โคลนที่เก็บ Github จากบรรทัดคำสั่งโดยใช้คำสั่งต่อไปนี้
$ git clone https://github.com/android/codelab-android-performance.git
หรือจะดาวน์โหลดไฟล์ ZIP 2 ไฟล์ก็ได้
เปิดโปรเจ็กต์ใน Android Studio
- ในหน้าต่าง Welcome to Android Studio ให้เลือก
Open an Existing Project - เลือกโฟลเดอร์
[Download Location]/codelab-android-performance/baseline-profilesตรวจสอบว่าคุณเลือกไดเรกทอรีbaseline-profiles - เมื่อ Android Studio นำเข้าโปรเจ็กต์แล้ว ให้ตรวจสอบว่าคุณเรียกใช้โมดูล
appเพื่อสร้างแอปพลิเคชันตัวอย่างที่คุณจะใช้ในภายหลังได้
แอปตัวอย่าง
ใน Codelab นี้ คุณจะได้ทำงานกับแอปพลิเคชันตัวอย่าง JetSnack ซึ่งเป็นแอปสั่งซื้อของว่างเสมือนที่ใช้ Jetpack Compose
หากต้องการวัดประสิทธิภาพของแอปพลิเคชัน คุณต้องเข้าใจโครงสร้างของ UI และลักษณะการทำงานของแอป เพื่อให้เข้าถึงองค์ประกอบ UI จากการเปรียบเทียบได้ เรียกใช้แอปและทำความคุ้นเคยกับหน้าจอพื้นฐานด้วยการสั่งซื้อของว่าง คุณไม่จำเป็นต้องทราบรายละเอียดเกี่ยวกับสถาปัตยกรรมของแอป

3. โปรไฟล์พื้นฐานคืออะไร
โปรไฟล์พื้นฐานช่วยปรับปรุงความเร็วในการเรียกใช้โค้ดประมาณ 30% จากการเปิดตัวครั้งแรกโดยหลีกเลี่ยงขั้นตอนการตีความและการคอมไพล์แบบทันที (JIT) สำหรับเส้นทางโค้ดที่รวมไว้ การจัดส่ง Baseline Profile ในแอปหรือไลบรารีจะช่วยให้ Android Runtime (ART) สามารถเพิ่มประสิทธิภาพเส้นทางโค้ดที่รวมไว้ผ่านการคอมไพล์ Ahead of Time (AOT) ซึ่งจะช่วยเพิ่มประสิทธิภาพสำหรับผู้ใช้ใหม่ทุกคนและในการอัปเดตแอปทุกครั้ง การเพิ่มประสิทธิภาพที่แนะนำโดยโปรไฟล์ (PGO) นี้ช่วยให้แอปเพิ่มประสิทธิภาพการเริ่มต้น ลดการกระตุกของการโต้ตอบ และปรับปรุงประสิทธิภาพรันไทม์โดยรวมสำหรับผู้ใช้ปลายทางตั้งแต่การเปิดตัวครั้งแรก
เมื่อใช้ Baseline Profile การโต้ตอบของผู้ใช้ทั้งหมด เช่น การเริ่มต้นแอป การไปยังส่วนต่างๆ ระหว่างหน้าจอ หรือการเลื่อนดูเนื้อหา จะราบรื่นขึ้นตั้งแต่ครั้งแรกที่เรียกใช้ การเพิ่มความเร็วและการตอบสนองของแอปจะนำไปสู่การมีผู้ใช้ที่ใช้งานอยู่รายวันมากขึ้นและอัตราการเข้าชมซ้ำโดยเฉลี่ยที่สูงขึ้น
โปรไฟล์พื้นฐานช่วยแนะแนวทางการเพิ่มประสิทธิภาพนอกเหนือจากการเริ่มต้นแอปด้วยการโต้ตอบของผู้ใช้ทั่วไป ซึ่งจะช่วยปรับปรุงเวลาทำงานของแอปตั้งแต่การเปิดตัวครั้งแรก การคอมไพล์ AOT ที่มีคำแนะนำไม่ได้ขึ้นอยู่กับอุปกรณ์ของผู้ใช้ และสามารถทำได้ 1 ครั้งต่อการเผยแพร่ในเครื่องที่ใช้พัฒนาแทนที่จะเป็นอุปกรณ์เคลื่อนที่ การเผยแพร่รุ่นที่มี Baseline Profile จะช่วยให้การเพิ่มประสิทธิภาพแอปพร้อมใช้งานได้เร็วกว่าการใช้ Cloud Profile เพียงอย่างเดียวมาก
เมื่อไม่ได้ใช้ Baseline Profile ระบบจะคอมไพล์โค้ดแอปทั้งหมดแบบ JIT ในหน่วยความจำหลังจากที่ตีความแล้ว หรือจะคอมไพล์เป็นไฟล์ odex ในเบื้องหลังเมื่ออุปกรณ์ไม่ได้ใช้งาน จากนั้นผู้ใช้อาจได้รับประสบการณ์การใช้งานที่ไม่ดีนักเมื่อเรียกใช้แอปหลังจากติดตั้งหรืออัปเดตเป็นครั้งแรกก่อนที่จะมีการเพิ่มประสิทธิภาพเส้นทางใหม่
4. ตั้งค่าโมดูลเครื่องมือสร้างโปรไฟล์พื้นฐาน
คุณสร้าง Baseline Profile ได้ด้วยคลาสการทดสอบแบบมีเครื่องมือวัดซึ่งต้องเพิ่มโมดูล Gradle ใหม่ลงในโปรเจ็กต์ วิธีที่ง่ายที่สุดในการเพิ่มลงในโปรเจ็กต์คือใช้ตัวช่วยสร้างโมดูล Android Studio ที่มาพร้อมกับ Android Studio Hedgehog ขึ้นไป
เปิดหน้าต่างวิซาร์ดโมดูลใหม่โดยคลิกขวาที่โปรเจ็กต์หรือโมดูลในแผงโปรเจ็กต์ แล้วเลือกใหม่ > โมดูล

จากหน้าต่างที่เปิดอยู่ ให้เลือก Baseline Profile Generator จากแผงเทมเพลต

นอกเหนือจากพารามิเตอร์ปกติ เช่น ชื่อโมดูล ชื่อแพ็กเกจ ภาษา หรือภาษาการกำหนดค่าบิลด์แล้ว ยังมีอินพุต 2 รายการที่ไม่ปกติสำหรับโมดูลใหม่ ได้แก่ แอปพลิเคชันเป้าหมายและใช้อุปกรณ์ที่มีการจัดการ Gradle
แอปพลิเคชันเป้าหมายคือโมดูลแอปที่ใช้สร้างโปรไฟล์พื้นฐาน หากมีโมดูลแอปมากกว่า 1 โมดูลในโปรเจ็กต์ ให้เลือกโมดูลที่ต้องการเรียกใช้เครื่องมือสร้าง
ช่องทําเครื่องหมายใช้อุปกรณ์ที่มีการจัดการโดย Gradle จะตั้งค่าโมดูลให้เรียกใช้เครื่องมือสร้าง Baseline Profile ในโปรแกรมจําลอง Android ที่มีการจัดการโดยอัตโนมัติ อ่านเพิ่มเติมเกี่ยวกับอุปกรณ์ที่มีการจัดการจาก Gradle ได้ในขยายขนาดการทดสอบด้วยอุปกรณ์ที่มีการจัดการจาก Gradle หากยกเลิกการเลือกช่องนี้ เครื่องกำเนิดจะใช้อุปกรณ์ที่เชื่อมต่อ
เมื่อกำหนดรายละเอียดทั้งหมดเกี่ยวกับโมดูลใหม่แล้ว ให้คลิกเสร็จสิ้นเพื่อดำเนินการสร้างโมดูลต่อ
การเปลี่ยนแปลงที่วิซาร์ดโมดูลดำเนินการ
วิซาร์ดโมดูลจะทำการเปลี่ยนแปลงหลายอย่างในโปรเจ็กต์
โดยจะเพิ่มโมดูล Gradle ที่ชื่อ baselineprofile หรือชื่อที่คุณเลือกในวิซาร์ด
โมดูลนี้ใช้ปลั๊กอิน com.android.test ซึ่งจะบอก Gradle ไม่ให้รวมไว้ในแอปพลิเคชัน ดังนั้นจึงมีได้เฉพาะโค้ดการทดสอบหรือการเปรียบเทียบเท่านั้น นอกจากนี้ยังใช้ปลั๊กอิน androidx.baselineprofile ซึ่งช่วยให้สร้าง Baseline Profile โดยอัตโนมัติได้
วิซาร์ดจะทำการเปลี่ยนแปลงในโมดูลแอปพลิเคชันเป้าหมายที่คุณเลือกด้วย กล่าวโดยเจาะจงคือจะใช้ปลั๊กอิน androidx.baselineprofile เพิ่มทรัพยากร Dependency androidx.profileinstaller และเพิ่มทรัพยากร Dependency baselineProfile ลงในโมดูล build.gradle(.kts) ที่สร้างขึ้นใหม่
plugins {
id("androidx.baselineprofile")
}
dependencies {
// ...
implementation("androidx.profileinstaller:profileinstaller:1.3.0")
"baselineProfile"(project(mapOf("path" to ":baselineprofile")))
}
การเพิ่มทรัพยากร Dependency androidx.profileinstaller ช่วยให้คุณทำสิ่งต่อไปนี้ได้
- ยืนยันการเพิ่มประสิทธิภาพของ Baseline Profile ที่สร้างขึ้นในเครื่อง
- ใช้ Baseline Profiles ใน Android 7 (API ระดับ 24) และ Android 8 (API ระดับ 26) ซึ่งไม่รองรับ Cloud Profiles
- ใช้โปรไฟล์พื้นฐานในอุปกรณ์ที่ไม่มีบริการ Google Play
baselineProfile(project(":baselineprofile")) Dependency ช่วยให้ Gradle ทราบว่าต้องใช้ Baseline Profile ที่สร้างขึ้นจากโมดูลใด
เมื่อตั้งค่าโปรเจ็กต์แล้ว ให้เขียนคลาสเครื่องมือสร้างโปรไฟล์พื้นฐาน
5. เขียนเครื่องมือสร้างโปรไฟล์พื้นฐาน
โดยปกติแล้ว คุณจะสร้างโปรไฟล์พื้นฐานสำหรับเส้นทางของผู้ใช้ทั่วไปของแอป
วิซาร์ดโมดูลจะสร้างBaselineProfileGeneratorคลาสทดสอบพื้นฐานที่สร้างโปรไฟล์พื้นฐานสำหรับการเริ่มต้นแอปได้ และมีลักษณะดังนี้
@RunWith(AndroidJUnit4::class)
@LargeTest
class BaselineProfileGenerator {
@get:Rule
val rule = BaselineProfileRule()
@Test
fun generate() {
rule.collect("com.example.baselineprofiles_codelab") {
// This block defines the app's critical user journey. This is where you
// optimize for app startup. You can also navigate and scroll
// through your most important UI.
// Start default activity for your app.
pressHome()
startActivityAndWait()
// TODO Write more interactions to optimize advanced journeys of your app.
// For example:
// 1. Wait until the content is asynchronously loaded.
// 2. Scroll the feed content.
// 3. Navigate to detail screen.
// Check UiAutomator documentation for more information about how to interact with the app.
// https://d.android.com/training/testing/other-components/ui-automator
}
}
}
คลาสนี้ใช้BaselineProfileRuleกฎการทดสอบและมีเมธอดการทดสอบ 1 รายการสำหรับการสร้างโปรไฟล์ จุดแรกเข้าสำหรับการสร้างโปรไฟล์คือฟังก์ชัน collect() โดยต้องใช้พารามิเตอร์เพียง 2 รายการ ได้แก่
packageName: แพ็กเกจของแอปprofileBlock: พารามิเตอร์ Lambda สุดท้าย
ใน profileBlock lambda คุณจะระบุการโต้ตอบที่ครอบคลุมเส้นทางของผู้ใช้ทั่วไปของแอป ไลบรารีจะเรียกใช้ profileBlock หลายครั้ง รวบรวมคลาสและฟังก์ชันที่เรียกใช้ และสร้าง Baseline Profile ในอุปกรณ์ด้วยโค้ดที่จะเพิ่มประสิทธิภาพ
โดยค่าเริ่มต้น คลาสเครื่องกำเนิดที่สร้างขึ้นจะมีการโต้ตอบเพื่อเริ่ม Activity เริ่มต้น และรอจนกว่าเฟรมแรกของแอปจะได้รับการแสดงผลโดยใช้วิธี startActivityAndWait()
ขยายเครื่องมือสร้างด้วยเส้นทางที่กำหนดเอง
คุณจะเห็นว่าคลาสที่สร้างขึ้นยังมี TODO บางส่วนเพื่อเขียนการโต้ตอบเพิ่มเติมเพื่อเพิ่มประสิทธิภาพเส้นทางขั้นสูงของแอปด้วย ซึ่งเราขอแนะนำให้ทำเช่นนี้เพื่อให้คุณเพิ่มประสิทธิภาพได้นอกเหนือจากการเริ่มต้นแอป
ในแอปตัวอย่าง คุณสามารถระบุเส้นทางเหล่านี้ได้โดยทำดังนี้
- เริ่มแอปพลิเคชัน ซึ่งชั้นเรียนที่สร้างขึ้นจะครอบคลุมส่วนนี้อยู่แล้ว
- รอจนกว่าระบบจะโหลดเนื้อหาแบบไม่พร้อมกัน
- เลื่อนดูรายการของว่าง
- ไปที่รายละเอียดของว่าง
เปลี่ยนเครื่องมือสร้างให้มีฟังก์ชันที่ระบุไว้ซึ่งครอบคลุมเส้นทางทั่วไปในข้อมูลโค้ดต่อไปนี้
// ...
rule.collect("com.example.baselineprofiles_codelab") {
// This block defines the app's critical user journey. This is where you
// optimize for app startup. You can also navigate and scroll
// through your most important UI.
// Start default activity for your app.
pressHome()
startActivityAndWait()
// TODO Write more interactions to optimize advanced journeys of your app.
// For example:
// 1. Wait until the content is asynchronously loaded.
waitForAsyncContent()
// 2. Scroll the feed content.
scrollSnackListJourney()
// 3. Navigate to detail screen.
goToSnackDetailJourney()
// Check UiAutomator documentation for more information about how to interact with the app.
// https://d.android.com/training/testing/other-components/ui-automator
}
// ...
ตอนนี้ให้เขียนการโต้ตอบสำหรับเส้นทางที่กล่าวถึงแต่ละเส้นทาง คุณสามารถเขียนเป็นฟังก์ชันส่วนขยายของ MacrobenchmarkScope เพื่อให้คุณมีสิทธิ์เข้าถึงพารามิเตอร์และฟังก์ชันที่ฟังก์ชันนี้มีให้ การเขียนในลักษณะนี้ช่วยให้คุณนำการโต้ตอบกับเกณฑ์เปรียบเทียบกลับมาใช้ใหม่เพื่อยืนยันการเพิ่มประสิทธิภาพได้
รอเนื้อหาแบบไม่พร้อมกัน
แอปจำนวนมากมีการโหลดแบบไม่พร้อมกันเมื่อเริ่มต้นแอป หรือที่เรียกว่าสถานะที่แสดงอย่างสมบูรณ์ ซึ่งจะบอกระบบเมื่อโหลดและแสดงเนื้อหา และผู้ใช้สามารถโต้ตอบกับเนื้อหาได้ รอสถานะในเครื่องกำเนิดไฟฟ้า (waitForAsyncContent) ด้วยการโต้ตอบต่อไปนี้
- ค้นหารายการของว่างในฟีด
- รอจนกว่ารายการบางรายการในลิสต์จะปรากฏบนหน้าจอ
fun MacrobenchmarkScope.waitForAsyncContent() {
device.wait(Until.hasObject(By.res("snack_list")), 5_000)
val contentList = device.findObject(By.res("snack_list"))
// Wait until a snack collection item within the list is rendered.
contentList.wait(Until.hasObject(By.res("snack_collection")), 5_000)
}
เส้นทางการเลื่อนรายการ
สำหรับการเดินทางในรายการของว่างที่เลื่อนได้ (scrollSnackListJourney) คุณสามารถทำตามการโต้ตอบต่อไปนี้
- ค้นหาองค์ประกอบ UI ของรายการของว่าง
- ตั้งค่าขอบท่าทางสัมผัสไม่ให้ทริกเกอร์การนำทางของระบบ
- เลื่อนรายการและรอจนกว่า UI จะเสร็จสมบูรณ์
fun MacrobenchmarkScope.scrollSnackListJourney() {
val snackList = device.findObject(By.res("snack_list"))
// Set gesture margin to avoid triggering gesture navigation.
snackList.setGestureMargin(device.displayWidth / 5)
snackList.fling(Direction.DOWN)
device.waitForIdle()
}
ไปที่เส้นทางรายละเอียด
เส้นทางสุดท้าย (goToSnackDetailJourney) จะใช้การโต้ตอบต่อไปนี้
- ค้นหารายการของว่างและรายการของว่างทั้งหมดที่คุณใช้ได้
- เลือกรายการจากรายการ
- คลิกรายการและรอจนกว่าหน้าจอรายละเอียดจะโหลด คุณสามารถใช้ประโยชน์จากข้อเท็จจริงที่ว่ารายการของว่างจะไม่แสดงบนหน้าจออีกต่อไป
fun MacrobenchmarkScope.goToSnackDetailJourney() {
val snackList = device.findObject(By.res("snack_list"))
val snacks = snackList.findObjects(By.res("snack_item"))
// Select snack from the list based on running iteration.
val index = (iteration ?: 0) % snacks.size
snacks[index].click()
// Wait until the screen is gone = the detail is shown.
device.wait(Until.gone(By.res("snack_list")), 5_000)
}
หลังจากกำหนดการโต้ตอบทั้งหมดที่จำเป็นสำหรับเครื่องมือสร้างโปรไฟล์พื้นฐานให้พร้อมใช้งานแล้ว คุณต้องกำหนดอุปกรณ์ที่จะใช้เรียกใช้
6. เตรียมอุปกรณ์เพื่อเรียกใช้เครื่องมือสร้าง
หากต้องการสร้าง Baseline Profile เราขอแนะนำให้ใช้โปรแกรมจำลอง เช่น อุปกรณ์ที่ Gradle จัดการ หรืออุปกรณ์ที่ใช้ Android 13 (API 33) ขึ้นไป
หากต้องการทำให้กระบวนการทำซ้ำได้และสร้าง Baseline Profile โดยอัตโนมัติ คุณสามารถใช้อุปกรณ์ที่มีการจัดการจาก Gradle ได้ อุปกรณ์ที่มีการจัดการจาก Gradle ช่วยให้คุณเรียกใช้การทดสอบในโปรแกรมจำลอง Android ได้โดยไม่ต้องเปิดและปิดด้วยตนเอง ดูข้อมูลเพิ่มเติมเกี่ยวกับอุปกรณ์ที่มีการจัดการจาก Gradle ได้ในขยายขนาดการทดสอบด้วยอุปกรณ์ที่มีการจัดการจาก Gradle
หากต้องการกำหนดอุปกรณ์ที่มีการจัดการของ Gradle ให้เพิ่มคำจำกัดความลงในไฟล์ :baselineprofileโมดูลbuild.gradle.ktsตามที่แสดงในข้อมูลโค้ดต่อไปนี้
android {
// ...
testOptions.managedDevices.devices {
create<ManagedVirtualDevice>("pixel6Api31") {
device = "Pixel 6"
apiLevel = 31
systemImageSource = "aosp"
}
}
}
ในกรณีนี้ เราใช้ Android 11 (API ระดับ 31) และอิมเมจระบบ aosp สามารถเข้าถึงรูทได้
จากนั้นกำหนดค่าปลั๊กอิน Gradle ของ Baseline Profile ให้ใช้อุปกรณ์ที่มีการจัดการจาก Gradle ที่กำหนดไว้ โดยให้เพิ่มชื่ออุปกรณ์ลงในพร็อพเพอร์ตี้ managedDevices และปิดใช้ useConnectedDevices ตามที่แสดงในข้อมูลโค้ดต่อไปนี้
android {
// ...
}
baselineProfile {
managedDevices += "pixel6Api31"
useConnectedDevices = false
}
dependencies {
// ...
}
จากนั้นสร้าง Baseline Profile
7. สร้างโปรไฟล์พื้นฐาน
เมื่ออุปกรณ์พร้อมแล้ว คุณจะสร้าง Baseline Profile ได้ ปลั๊กอิน Gradle ของ Baseline Profile จะสร้างงาน Gradle เพื่อทำให้กระบวนการทั้งหมดของการเรียกใช้คลาสทดสอบเครื่องมือสร้างและการใช้ Baseline Profile ที่สร้างขึ้นในแอปเป็นแบบอัตโนมัติ
วิซาร์ดโมดูลใหม่ได้สร้างการกำหนดค่าการเรียกใช้เพื่อให้เรียกใช้ Gradle Task ได้อย่างรวดเร็วด้วยพารามิเตอร์ที่จำเป็นทั้งหมดเพื่อเรียกใช้โดยไม่ต้องสลับระหว่างเทอร์มินัลกับ Android Studio
หากต้องการเรียกใช้ ให้ค้นหาGenerate Baseline Profileการกำหนดค่าการเรียกใช้ แล้วคลิกปุ่มเรียกใช้ 

งานจะเริ่มอิมเมจโปรแกรมจำลองที่กำหนดไว้ก่อนหน้านี้ เรียกใช้การโต้ตอบจากBaselineProfileGeneratorชั้นเรียนทดสอบหลายครั้ง จากนั้นให้ปิดโปรแกรมจำลองและระบุเอาต์พุตไปยัง Android Studio
เมื่อเครื่องมือสร้างทำงานเสร็จเรียบร้อยแล้ว ปลั๊กอิน Gradle จะใส่ baseline-prof.txt ที่สร้างขึ้นลงในแอปพลิเคชันเป้าหมาย (โมดูล :app) ในโฟลเดอร์ src/release/generated/baselineProfile/ โดยอัตโนมัติ

(ไม่บังคับ) เรียกใช้เครื่องมือสร้างจากบรรทัดคำสั่ง
หรือจะเรียกใช้เครื่องมือสร้างจากบรรทัดคำสั่งก็ได้ คุณใช้ประโยชน์จากงานที่สร้างโดยอุปกรณ์ที่มีการจัดการจาก Gradle ได้ ซึ่งก็คือ :app:generateBaselineProfile คำสั่งนี้จะเรียกใช้การทดสอบทั้งหมดในโปรเจ็กต์ที่กำหนดโดยการขึ้นต่อกัน baselineProfile(project(:baselineProfile)) เนื่องจากโมดูลยังมีเกณฑ์เปรียบเทียบสำหรับการยืนยันผลลัพธ์ที่ได้ในภายหลัง การทดสอบเหล่านั้นจึงล้มเหลวพร้อมคำเตือนไม่ให้เรียกใช้เกณฑ์เปรียบเทียบในโปรแกรมจำลอง
android .testInstrumentationRunnerArguments .androidx.benchmark.enabledRules=BaselineProfile
คุณสามารถกรองเครื่องมือสร้าง Baseline Profile ทั้งหมดได้โดยใช้การอาร์กิวเมนต์ของเครื่องมือเรียกใช้การวัดประสิทธิภาพต่อไปนี้ และระบบจะข้ามการวัดประสิทธิภาพทั้งหมด
คำสั่งทั้งหมดมีลักษณะดังนี้
./gradlew :app:generateBaselineProfile -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile
เผยแพร่แอปด้วย Baseline Profile
เมื่อสร้างและคัดลอก Baseline Profile ลงในซอร์สโค้ดของแอปแล้ว ให้สร้างแอปเวอร์ชันที่ใช้งานจริงตามปกติ คุณไม่จำเป็นต้องดำเนินการใดๆ เพิ่มเติมเพื่อเผยแพร่ Baseline Profile ให้กับผู้ใช้ ปลั๊กอิน Android Gradle จะเลือกทรัพยากรเหล่านี้ในระหว่างการบิลด์และรวมไว้ใน AAB หรือ APK จากนั้นอัปโหลดบิลด์ไปยัง Google Play
เมื่อผู้ใช้ติดตั้งหรืออัปเดตแอปจากเวอร์ชันก่อนหน้า ระบบจะติดตั้ง Baseline Profile ด้วย ซึ่งจะส่งผลให้แอปมีประสิทธิภาพดีขึ้นตั้งแต่การเรียกใช้ครั้งแรก
ขั้นตอนถัดไปจะแสดงวิธีตรวจสอบว่าประสิทธิภาพของแอปดีขึ้นมากน้อยเพียงใดเมื่อใช้โปรไฟล์พื้นฐาน
8. (ไม่บังคับ) ปรับแต่งการสร้างโปรไฟล์พื้นฐาน
ปลั๊กอิน Gradle ของ Baseline Profiles มีตัวเลือกในการปรับแต่งวิธีสร้างโปรไฟล์ให้ตรงกับความต้องการเฉพาะของคุณ คุณเปลี่ยนลักษณะการทำงานได้ด้วยbaselineProfile { }บล็อกการกำหนดค่าในสคริปต์บิลด์
บล็อกการกำหนดค่าภายในโมดูล :baselineprofile จะส่งผลต่อวิธีเรียกใช้เครื่องมือสร้างโดยมีความเป็นไปได้ที่จะเพิ่ม managedDevices และตัดสินใจว่าจะใช้ useConnectedDevices หรืออุปกรณ์ที่จัดการโดย Gradle
บล็อกการกำหนดค่าภายใน:appโมดูลเป้าหมายจะกำหนดตำแหน่งที่จะบันทึกโปรไฟล์หรือวิธีกำหนดค่าโปรไฟล์ คุณสามารถเปลี่ยนพารามิเตอร์ต่อไปนี้ได้
automaticGenerationDuringBuild: หากเปิดใช้ คุณจะสร้าง Baseline Profile ได้เมื่อสร้างบิลด์เวอร์ชันที่ใช้งานจริง ซึ่งจะเป็นประโยชน์เมื่อสร้างบน CI ก่อนที่จะจัดส่งแอปsaveInSrc: ระบุว่าจะจัดเก็บ Baseline Profile ที่สร้างขึ้นในโฟลเดอร์src/หรือไม่ หรือจะเข้าถึงไฟล์จากโฟลเดอร์บิลด์:baselineprofileก็ได้baselineProfileOutputDir: กำหนดตำแหน่งที่จะจัดเก็บโปรไฟล์พื้นฐานที่สร้างขึ้นmergeIntoMain: โดยค่าเริ่มต้น ระบบจะสร้างโปรไฟล์พื้นฐานต่อตัวแปรบิลด์ (รสชาติของผลิตภัณฑ์และประเภทบิลด์) หากต้องการผสานโปรไฟล์ทั้งหมดเข้ากับsrc/mainคุณสามารถทำได้โดยเปิดใช้ฟีเจอร์นี้filter: คุณสามารถกรองคลาสหรือเมธอดที่จะรวมหรือยกเว้นจาก Baseline Profile ที่สร้างขึ้นได้ ซึ่งอาจเป็นประโยชน์สำหรับนักพัฒนาไลบรารีที่ต้องการรวมเฉพาะโค้ดจากไลบรารี
9. ยืนยันการปรับปรุงประสิทธิภาพการเริ่มต้นระบบ
หลังจากสร้าง Baseline Profile และเพิ่มลงในแอปแล้ว ให้ตรวจสอบว่าโปรไฟล์ดังกล่าวส่งผลต่อประสิทธิภาพของแอปตามที่คุณต้องการ
วิซาร์ดโมดูลใหม่จะสร้างคลาสการเปรียบเทียบที่ชื่อ StartupBenchmarks ซึ่งมีเกณฑ์มาตรฐานสำหรับวัดเวลาเริ่มต้นแอปและเปรียบเทียบกับเวลาที่แอปใช้ Baseline Profile
โดยคลาสจะมีลักษณะดังนี้
@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.example.baselineprofiles_codelab",
metrics = listOf(StartupTimingMetric()),
compilationMode = compilationMode,
startupMode = StartupMode.COLD,
iterations = 10,
setupBlock = {
pressHome()
},
measureBlock = {
startActivityAndWait()
// TODO Add interactions to wait for when your app is fully drawn.
// The app is fully drawn when Activity.reportFullyDrawn is called.
// For Jetpack Compose, you can use ReportDrawn, ReportDrawnWhen and ReportDrawnAfter
// from the AndroidX Activity library.
// Check the UiAutomator documentation for more information on how to
// interact with the app.
// https://d.android.com/training/testing/other-components/ui-automator
}
)
}
}
โดยใช้ MacrobenchmarkRule ที่สามารถเรียกใช้การเปรียบเทียบสำหรับแอปและรวบรวมเมตริกประสิทธิภาพ จุดแรกเข้าสำหรับการเขียนการเปรียบเทียบคือฟังก์ชัน measureRepeated จากกฎ
โดยต้องใช้พารามิเตอร์หลายรายการ ดังนี้
packageName:แอปพลิเคชันที่จะวัดmetrics: ประเภทของข้อมูลที่คุณต้องการวัดระหว่างการเปรียบเทียบiterations: จำนวนครั้งที่การเปรียบเทียบซ้ำstartupMode: วิธีที่คุณต้องการให้แอปพลิเคชันเริ่มต้นเมื่อเริ่มการเปรียบเทียบsetupBlock: การโต้ตอบกับแอปที่ต้องเกิดขึ้นก่อนการวัดmeasureBlock: การโต้ตอบกับแอปที่คุณต้องการวัดในระหว่างการเปรียบเทียบ
คลาสการทดสอบยังมีการทดสอบ 2 รายการ ได้แก่ startupCompilationeNone() และ startupCompilationBaselineProfiles() ซึ่งเรียกใช้ฟังก์ชัน benchmark() ด้วย compilationMode ที่แตกต่างกัน
CompilationMode
พารามิเตอร์ CompilationMode จะกำหนดวิธีที่แอปพลิเคชันได้รับการคอมไพล์ล่วงหน้าเป็นโค้ดเครื่อง โดยมีตัวเลือกดังนี้
DEFAULT: คอมไพล์แอปบางส่วนล่วงหน้าโดยใช้ Baseline Profile หากมี ระบบจะใช้พารามิเตอร์นี้หากไม่มีการใช้พารามิเตอร์compilationModeNone(): รีเซ็ตสถานะการคอมไพล์แอปและไม่ได้คอมไพล์แอปล่วงหน้า การคอมไพล์แบบทันที (JIT) จะยังคงเปิดใช้ในระหว่างการเรียกใช้แอปPartial(): คอมไพล์ล่วงหน้าสำหรับแอปด้วย Baseline Profile หรือการเรียกใช้แบบวอร์มอัป หรือทั้ง 2 อย่างFull(): คอมไพล์โค้ดแอปพลิเคชันทั้งหมดล่วงหน้า ตัวเลือกนี้เป็นตัวเลือกเดียวใน Android 6 (API 23) และต่ำกว่า
หากต้องการเริ่มเพิ่มประสิทธิภาพแอปพลิเคชัน คุณสามารถเลือกDEFAULTโหมดการคอมไพล์ เนื่องจากประสิทธิภาพจะคล้ายกับเมื่อติดตั้งแอปจาก Google Play หากต้องการเปรียบเทียบประโยชน์ด้านประสิทธิภาพที่โปรไฟล์พื้นฐานมอบให้ คุณสามารถทำได้โดยเปรียบเทียบผลลัพธ์ของโหมดการคอมไพล์ None และ Partial
แก้ไขเกณฑ์มาตรฐานให้รอเนื้อหา
การเปรียบเทียบจะเขียนในลักษณะเดียวกับเครื่องมือสร้างโปรไฟล์พื้นฐานโดยการเขียนการโต้ตอบกับแอปของคุณ โดยค่าเริ่มต้น การเปรียบเทียบที่สร้างขึ้นจะรอเฉพาะเฟรมแรกที่จะแสดงผล ซึ่งคล้ายกับวิธีที่ BaselineProfileGenerator ทำ ดังนั้นเราขอแนะนำให้ปรับปรุงให้รอเนื้อหาแบบไม่พร้อมกัน
คุณทำได้โดยใช้ฟังก์ชันส่วนขยายที่คุณเขียนสำหรับเครื่องมือสร้างซ้ำ เนื่องจากเกณฑ์นี้จะบันทึกเวลาเริ่มต้นโดยใช้ StartupTimingMetric() เราจึงขอแนะนำให้คุณรวมเฉพาะการรอเนื้อหาแบบอะซิงโครนัสไว้ที่นี่ จากนั้นเขียนเกณฑ์แยกต่างหากสำหรับเส้นทางของผู้ใช้ที่เหลือซึ่งกำหนดไว้ในเครื่องมือสร้าง
// ...
measureBlock = {
startActivityAndWait()
// The app is fully drawn when Activity.reportFullyDrawn is called.
// For Jetpack Compose, you can use ReportDrawn, ReportDrawnWhen and ReportDrawnAfter
// from the AndroidX Activity library.
waitForAsyncContent() // <------- Added to wait for async content.
// Check the UiAutomator documentation for more information on how to
// interact with the app.
// https://d.android.com/training/testing/other-components/ui-automator
}
เรียกใช้การเปรียบเทียบ
คุณเรียกใช้การทดสอบประสิทธิภาพได้ในลักษณะเดียวกับการเรียกใช้การทดสอบที่มีการวัดคุม คุณสามารถเรียกใช้ฟังก์ชันทดสอบหรือทั้งชั้นเรียนได้โดยใช้ไอคอนแถบด้านข้างที่อยู่ถัดจากฟังก์ชัน

ตรวจสอบว่าคุณได้เลือกอุปกรณ์จริงแล้ว เนื่องจากการเรียกใช้การเปรียบเทียบในโปรแกรมจำลอง Android จะล้มเหลวในรันไทม์พร้อมคำเตือนว่าการเปรียบเทียบอาจให้ผลลัพธ์ที่ไม่ถูกต้อง แม้ว่าในทางเทคนิคแล้วคุณจะเรียกใช้บนโปรแกรมจำลองได้ แต่คุณกำลังวัดประสิทธิภาพของเครื่องโฮสต์ หากมีการใช้งานหนัก เกณฑ์เปรียบเทียบจะทำงานช้าลงและในทางกลับกัน

เมื่อคุณเรียกใช้การเปรียบเทียบแล้ว ระบบจะสร้างแอปของคุณใหม่ จากนั้นจะเรียกใช้การเปรียบเทียบ โดยจะเริ่ม หยุด และแม้กระทั่งติดตั้งแอปของคุณซ้ำหลายครั้งตามiterationsที่คุณกำหนด
หลังจากเกณฑ์มาตรฐานเสร็จสมบูรณ์ คุณจะเห็นเวลาในเอาต์พุตของ Android Studio ดังที่แสดงในภาพหน้าจอต่อไปนี้

จากภาพหน้าจอ คุณจะเห็นว่าเวลาเริ่มต้นของแอปจะแตกต่างกันสำหรับแต่ละ CompilationMode ค่ามัธยฐานแสดงอยู่ในตารางต่อไปนี้
timeToInitialDisplay [มิลลิวินาที] | timeToFullDisplay [มิลลิวินาที] | |
ไม่มี | 202.2 | 818.8 |
BaselineProfiles | 193.7 | 637.9 |
การปรับปรุง | 4% | 28% |
ความแตกต่างระหว่างโหมดการคอมไพล์สำหรับ timeToFullDisplay คือ 180 มิลลิวินาที ซึ่งเป็นการปรับปรุงประมาณ 28% เพียงแค่มีโปรไฟล์พื้นฐาน CompilationNone ทำงานได้แย่กว่าเนื่องจากอุปกรณ์ต้องทำการคอมไพล์ JIT มากที่สุดในระหว่างการเริ่มต้นแอป ส่วน CompilationBaselineProfiles ทำงานได้ดีกว่าเนื่องจากการคอมไพล์บางส่วนด้วย Baseline Profile จะคอมไพล์ AOT โค้ดที่ผู้ใช้มีแนวโน้มที่จะใช้มากที่สุด และปล่อยให้โค้ดที่ไม่สำคัญไม่ได้คอมไพล์ล่วงหน้าเพื่อไม่ให้ต้องโหลดทันที
10. (ไม่บังคับ) ยืนยันการปรับปรุงประสิทธิภาพการเลื่อน
คุณสามารถวัดและยืนยันประสิทธิภาพการเลื่อนได้เช่นเดียวกับขั้นตอนก่อนหน้า ก่อนอื่น ให้สร้างScrollBenchmarksคลาสทดสอบที่มีกฎการวัดประสิทธิภาพและเมธอดทดสอบ 2 รายการที่ใช้โหมดการคอมไพล์ที่แตกต่างกัน ดังนี้
@LargeTest
@RunWith(AndroidJUnit4::class)
class ScrollBenchmarks {
@get:Rule
val rule = MacrobenchmarkRule()
@Test
fun scrollCompilationNone() = scroll(CompilationMode.None())
@Test
fun scrollCompilationBaselineProfiles() = scroll(CompilationMode.Partial())
private fun scroll(compilationMode: CompilationMode) {
// TODO implement
}
}
จากภายในเมธอด scroll ให้ใช้ฟังก์ชัน measureRepeated กับพารามิเตอร์ที่จำเป็น สําหรับพารามิเตอร์ metrics ให้ใช้ FrameTimingMetric ซึ่งจะวัดระยะเวลาที่ใช้ในการสร้างเฟรม UI
private fun scroll(compilationMode: CompilationMode) {
rule.measureRepeated(
packageName = "com.example.baselineprofiles_codelab",
metrics = listOf(FrameTimingMetric()),
compilationMode = compilationMode,
startupMode = StartupMode.WARM,
iterations = 10,
setupBlock = {
// TODO implement
},
measureBlock = {
// TODO implement
}
)
}
คราวนี้คุณต้องแบ่งการโต้ตอบระหว่าง setupBlock กับ measureBlock ให้มากขึ้นเพื่อวัดระยะเวลาเฟรมระหว่างเลย์เอาต์แรกและการเลื่อนเนื้อหาเท่านั้น ดังนั้น ให้ใส่ฟังก์ชันที่เริ่มหน้าจอเริ่มต้นไว้ใน setupBlock และฟังก์ชันส่วนขยายที่สร้างไว้แล้ว waitForAsyncContent() และ scrollSnackListJourney() ไว้ใน measureBlock
private fun scroll(compilationMode: CompilationMode) {
rule.measureRepeated(
packageName = "com.example.baselineprofiles_codelab",
metrics = listOf(FrameTimingMetric()),
compilationMode = compilationMode,
startupMode = StartupMode.WARM,
iterations = 10,
setupBlock = {
pressHome()
startActivityAndWait()
},
measureBlock = {
waitForAsyncContent()
scrollSnackListJourney()
}
)
}
เมื่อการทดสอบพร้อมแล้ว คุณจะเรียกใช้การทดสอบได้เหมือนเดิมเพื่อดูผลลัพธ์ตามที่แสดงในภาพหน้าจอต่อไปนี้

FrameTimingMetric เอาต์พุตระยะเวลาของเฟรมเป็นมิลลิวินาที (frameDurationCpuMs) ในเปอร์เซ็นไทล์ที่ 50, 90, 95 และ 99 ใน Android 12 (API ระดับ 31) ขึ้นไป ระบบจะแสดงระยะเวลาที่เฟรมของคุณเกินขีดจำกัด (frameOverrunMs) ด้วย ค่าอาจเป็นค่าลบ ซึ่งหมายความว่ามีเวลาเหลือในการสร้างเฟรม
จากผลลัพธ์ คุณจะเห็นว่า CompilationBaselineProfiles มีระยะเวลาเฟรมสั้นกว่าโดยเฉลี่ย 2 มิลลิวินาที ซึ่งผู้ใช้อาจไม่สังเกตเห็น อย่างไรก็ตาม สำหรับเปอร์เซ็นไทล์อื่นๆ ผลลัพธ์จะชัดเจนกว่า สำหรับ P99 ความแตกต่างคือ 43.5 มิลลิวินาที ซึ่งมากกว่า 3 เฟรมที่ข้ามในอุปกรณ์ที่ทำงานที่ 90 FPS เช่น สำหรับ Pixel 6 คือ 1, 000 มิลลิวินาที / 90 FPS = เวลาสูงสุดประมาณ 11 มิลลิวินาทีในการแสดงผลเฟรม
11. ขอแสดงความยินดี
ขอแสดงความยินดี คุณทำ Codelab นี้เสร็จสมบูรณ์แล้วและปรับปรุงประสิทธิภาพของแอปด้วย Baseline Profile
แหล่งข้อมูลเพิ่มเติม
ดูแหล่งข้อมูลเพิ่มเติมต่อไปนี้
- ตรวจสอบประสิทธิภาพของแอปด้วย Macrobenchmark: Codelab ที่เจาะลึกเรื่องการเปรียบเทียบ
- ตัวอย่างประสิทธิภาพ: ที่เก็บข้อมูลที่มี Macrobenchmark และตัวอย่างประสิทธิภาพอื่นๆ
- แอปตัวอย่าง Now In Android: แอปพลิเคชันในโลกแห่งความเป็นจริงที่ใช้การเปรียบเทียบและโปรไฟล์พื้นฐานเพื่อปรับปรุงประสิทธิภาพ