เมตริกคือข้อมูลประเภทหลักที่ดึงมาจากการเปรียบเทียบ โดยจะส่งไปยังฟังก์ชัน measureRepeated เป็น List ซึ่งช่วยให้คุณระบุเมตริกที่วัดได้หลายรายการพร้อมกัน ต้องระบุเมตริกอย่างน้อย 1 ประเภทเพื่อให้การเปรียบเทียบทํางานได้
ข้อมูลโค้ดต่อไปนี้จะบันทึกการจับเวลาเฟรมและเมตริกส่วนการติดตามที่กําหนดเอง สําหรับอินเทอร์เฟซเลย์เอาต์แบบ Lazy ของ Jetpack Compose
@OptIn(ExperimentalMetricApi::class)
@Test
fun scrollComposeList() {
benchmarkRule.measureRepeated(
// [START_EXCLUDE]
packageName = TARGET_PACKAGE,
metrics = listOf(
FrameTimingMetric(),
// Measure power usage. This is supported on Pixel 6 and later.
PowerMetric(PowerMetric.Type.Power(
mapOf(
PowerCategory.CPU to PowerCategoryDisplayLevel.TOTAL,
PowerCategory.DISPLAY to PowerCategoryDisplayLevel.TOTAL,
PowerCategory.GPU to PowerCategoryDisplayLevel.TOTAL,
PowerCategory.NETWORK to PowerCategoryDisplayLevel.TOTAL,
)
)),
// Measure custom trace sections by name EntryRow (which is added to the EntryRow composable).
// Mode.Sum measures combined duration and also how many times it occurred in the trace.
// This way, you can estimate whether a composable recomposes more than it should.
TraceSectionMetric("EntryRowCustomTrace", TraceSectionMetric.Mode.Sum),
// This trace section takes into account the SQL wildcard character %,
// which can find trace sections without the full name.
// This way, you can measure composables produced by the composition tracing
// and measure how long they took and how many times they recomposed.
// WARNING: This metric only shows results when running with composition tracing, otherwise it won't be visible in the outputs.
TraceSectionMetric("%EntryRow%", TraceSectionMetric.Mode.Sum),
),
// Try switching to different compilation modes to see the effect
// it has on frame timing metrics.
compilationMode = CompilationMode.None(),
startupMode = StartupMode.WARM, // restarts activity each iteration
iterations = DEFAULT_ITERATIONS,
// [END_EXCLUDE]
setupBlock = {
uiAutomator {
// Before starting to measure, navigate to the UI to be measured.
startIntent(Intent("$packageName.COMPOSE_ACTIVITY"))
}
}
) {
uiAutomator {
onElement { isScrollable }.fling(Direction.DOWN)
}
}
}
ในตัวอย่างต่อไปนี้ EntryRowCustomTrace แสดงถึงส่วนการติดตามที่กำหนดเอง
ซึ่งกำหนดไว้ภายในเลเยอร์ของไอเทมที่ประกอบได้โดยใช้ตัวห่อบล็อก Kotlin
trace(sectionName) { ... } มาตรฐาน หากต้องการระบุข้อมูลสำหรับ
TraceSectionMetric คุณต้องห่อคอมโพเนนต์ UI เป้าหมายไว้ภายใน
ฐานของโค้ดเวอร์ชันที่ใช้งานจริงของแอปพลิเคชันด้วยรันไทม์ Jetpack มาตรฐานtrace
Block Wrapper
@Composable
private fun EntryRow(entry: Entry, modifier: Modifier = Modifier) = trace("EntryRowCustomTrace") {
Card(modifier = modifier) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
text = entry.contents,
modifier = Modifier
.padding(16.dp)
.wrapContentSize()
)
Spacer(modifier = Modifier.weight(1f))
Checkbox(
checked = false,
onCheckedChange = {},
modifier = Modifier.padding(16.dp)
)
}
}
}
ผลการเปรียบเทียบจะแสดงโดยตรงในแท็บเทอร์มินัลการเปรียบเทียบภายใน Android Studio ดังที่แสดงในรูปที่ 1 หากกำหนดเมตริกหลายรายการ ระบบจะรวมจุดข้อมูลที่คำนวณแล้วทั้งหมดไว้ในหน้าต่างสรุป
TraceSectionMetric และ FrameTimingMetric สำหรับเลย์เอาต์ Compose ที่ทันสมัยStartupTimingMetric, FrameTimingMetric, TraceSectionMetric และ
PowerMetric มีรายละเอียดอยู่ด้านล่าง ดูรายการเมตริกการเปรียบเทียบทั้งหมดที่พร้อมใช้งานได้ในคลาสย่อยของ Metric ในเอกสารอ้างอิง API
StartupTimingMetric
StartupTimingMetric จะบันทึกเมตริกเวลาเริ่มต้นของแอปด้วยค่าต่อไปนี้
timeToInitialDisplayMs: ระยะเวลาตั้งแต่ระบบได้รับ เจตนาในการเปิดแอปจนถึงตอนที่แสดงผลเฟรมแรกของหน้าจอปลายทางtimeToFullDisplayMs: ระยะเวลาตั้งแต่ระบบได้รับ Intent ในการเปิดตัวจนถึงเวลาที่แอปรายงานว่าวาดเสร็จสมบูรณ์โดยใช้กลไกการรายงานภายใน แพลตฟอร์ม การวัดจะหยุดเมื่อการแสดงผลเฟรมแรกเสร็จสมบูรณ์หลังจากหรือมีสัญญาณที่วาดเสร็จสมบูรณ์
StartupTimingMetric แสดงค่าต่ำสุด ค่ามัธยฐาน และค่าสูงสุดจากการ
การทำซ้ำของสตาร์ทอัป หากต้องการประเมินการปรับปรุงการเริ่มต้น ให้มุ่งเน้นค่ามัธยฐานเสมอ เนื่องจากค่ามัธยฐานให้ค่าประมาณที่ดีที่สุดของเวลาเริ่มต้นของผู้ใช้ทั่วไป
ในสถาปัตยกรรม Compose-first อย่าพยายามเรียกใช้
activity.reportFullyDrawn ด้วยตนเอง แต่ให้ใช้ยูทิลิตีแบบอะซิงโครนัสที่ปลอดภัยสำหรับ Compose อย่าง ReportDrawn, ReportDrawnWhen หรือ ReportDrawnAfter
ภายใน Composable ของหน้าจอเพื่อส่งสัญญาณไปยัง Macrobenchmark โดยอัตโนมัติเมื่อ
ข้อมูลเครือข่ายแบบอะซิงโครนัสหรือสถานะ UI ที่ซับซ้อนแสดงผลเสร็จแล้ว
ดูข้อมูลเพิ่มเติมเกี่ยวกับการวิเคราะห์และการเพิ่มประสิทธิภาพการเริ่มต้นได้ที่เวลาเริ่มต้นของแอป
FrameTimingMetric
FrameTimingMetric จะบันทึกข้อมูลเวลาที่แน่นอนจากเฟรม
ที่สร้างขึ้นโดยเส้นทางการทดสอบประสิทธิภาพ เช่น การเลื่อนรายการหรือเลย์เอาต์ของ UI ที่ซับซ้อน
ภาพเคลื่อนไหว และแสดงค่าการวินิจฉัยต่อไปนี้
frameOverrunMs: ระยะเวลาที่เฟรมหนึ่งๆ แสดงผลช้ากว่ากำหนด ตัวเลขที่เป็นค่าบวกแสดงถึงเฟรมที่ขาดหายไปพร้อมกับอาการกระตุกที่มองเห็นได้ หรือ การหยุดชะงัก ตัวเลขติดลบแสดงให้เห็นว่าเฟรมเสร็จสมบูรณ์เร็วขึ้นเท่าใด เมื่อเทียบกับกำหนดเวลาของฮาร์ดแวร์ของระบบย่อย หมายเหตุ: เมตริกนี้ใช้ได้ ใน Android 12 (ระดับ API 31) ขึ้นไปเท่านั้นframeDurationCpuMs: ระยะเวลาที่เฟรมใช้ในการสร้างบน CPU ทั้งในเธรด UI ของแอปพลิเคชันหลักและRenderThread
ระบบจะรวบรวมการวัดเหล่านี้ในการกระจายเปอร์เซ็นไทล์ที่ 50, 90, 95 และ 99 ดังนี้
frameDurationCpuMs P50 3.5, P90 6.0, P95 6.4, P99 11.0
frameOverrunMs P50 -11.6, P90 -7.2, P95 -7.1, P99 -1.2
เมื่อเพิ่มประสิทธิภาพลำดับชั้นของเลย์เอาต์ Jetpack Compose ให้ดูที่เฟรมที่มีประสิทธิภาพต่ำที่สุด (ขอบเขต P95 และ P99) หาก frameOverrunMs เพิ่มขึ้น
เป็นจำนวนเต็มบวกที่เปอร์เซ็นไทล์สูง แสดงว่าการจัดองค์ประกอบใหม่
กำลังทำให้เธรดหลักหยุดทำงานชั่วคราวระหว่างภาพเคลื่อนไหวการเลื่อนที่หนักหน่วง
ดูข้อมูลเชิงลึกเพิ่มเติมเกี่ยวกับการระบุและแก้ไขเฟรมที่ช้าได้ที่ประสิทธิภาพของ Jetpack Compose
TraceSectionMetric
TraceSectionMetric จะบันทึกจำนวนครั้งที่ส่วนการติดตามที่เฉพาะเจาะจง
เกิดขึ้นและระยะเวลาสัมบูรณ์ที่ใช้ในการดำเนินการ สำหรับการติดตามเวลา
จะแสดงเวลาต่ำสุด ค่ามัธยฐาน และเวลาสูงสุดเป็นมิลลิวินาที ส่วนเป้าหมาย การติดตามจะกําหนดโดยการเรียกใช้ฟังก์ชัน trace(sectionName) หรือขอบเขตบล็อกระดับล่างระหว่าง Trace.beginSection(sectionName) กับ Trace.endSection() หรือตัวแปรแบบไม่พร้อมกัน
EntryRowCustomTraceCount min 20.0, median 28.0, max 50.0
EntryRowCustomTraceSumMs min 34.9, median 44.4, max 66.6
โดยค่าเริ่มต้น เมตริกจะแสดงเฉพาะส่วนการติดตามที่คอมไพล์โดยตรงจากไบนารีของแพ็กเกจแอปพลิเคชันของคุณเอง
หากต้องการรวมกระบวนการที่มาจากภายนอกขอบเขตแพ็กเกจของแอป ให้ตั้งค่าพร็อพเพอร์ตี้ targetPackageOnly = false
เมื่อทำงานกับการติดตามรันไทม์ของ Jetpack Compose คุณจะแสดงฟังก์ชันที่ใช้ Composable แต่ละรายการในกราฟการติดตามระบบได้โดยไม่ต้องเขียน Wrapper การติดตามด้วยตนเองด้วยการเปิดใช้การติดตามการจัดองค์ประกอบ
แม้ว่าการเพิ่มทรัพยากร Dependency ของ androidx.compose.runtime:runtime-tracing ในแอปพลิเคชันเป้าหมายจะเพียงพอสำหรับการติดตามโปรไฟล์ด้วยตนเอง แต่การบันทึกการติดตามเหล่านี้แบบเป็นโปรแกรมภายในรัน Macrobenchmark ต้องมีการกำหนดค่าเพิ่มเติมภายในโมดูลการทดสอบ
ดูวิธีการตั้งค่าทั้งหมดได้ที่บันทึกการติดตามด้วย Jetpack Macrobenchmark
PowerMetric
PowerMetric จะบันทึกการเปลี่ยนแปลงของกำลังหรือพลังงานตลอดระยะเวลา
การเรียกใช้มาโครเบนช์มาร์ก ระบบจะแบ่งหมวดหมู่ที่เลือกแต่ละหมวดหมู่เป็น
คอมโพเนนต์ฮาร์ดแวร์ที่วัดผลได้ ส่วนหมวดหมู่ที่ไม่ได้เลือกจะจัดกลุ่มไว้ในที่เก็บข้อมูล "ไม่ได้เลือก"
ข้อกำหนดเกี่ยวกับฮาร์ดแวร์: เมตริกเหล่านี้จะวัดการใช้งานทั้งระบบ ไม่ใช่การคำนวณต่อแอป ด้วยเหตุนี้ การเก็บรวบรวมข้อมูลจึงจำกัดเฉพาะอุปกรณ์จริงของ Google Pixel 6, Pixel 6 Pro และอุปกรณ์จริงรุ่นใหม่กว่า
เมตริกจะแสดงการวัด 2 รายการต่อหมวดหมู่ ดังนี้
power<category>Uw: ปริมาณการใช้พลังงานตลอดระยะเวลาการทดสอบในหมวดหมู่นี้ (วัดเป็นไมโครวัตต์)energy<category>Uws: ปริมาณพลังงานทั้งหมดที่โอนต่อหน่วยเวลา ในระยะเวลาการทดสอบในหมวดหมู่นี้ (วัดเป็น ไมโครวัตต์-วินาที)
หมวดหมู่ต่างๆ มีดังนี้
CPUDISPLAYGPUGPSMEMORYMACHINE_LEARNINGNETWORKUNCATEGORIZED
ในบางหมวดหมู่ เช่น CPU การแยกงานที่กระบวนการอื่นๆ ทำออกจากงานที่แอปของคุณทำอาจเป็นเรื่องยาก เพื่อลดการรบกวน ให้ลบหรือจำกัดแอปและบัญชีที่ไม่จำเป็น
powerCategoryCpuUw min 300.2, median 346.1, max 519.6
powerCategoryDisplayUw min 319.8, median 325.8, max 329.7
powerCategoryGpuUw min 18.8, median 23.3, max 36.9
powerCategoryNetworkUw min 97.3, median 123.3, max 681.3
powerTotalUw min 1234.8, median 1316.6, max 2112.4
powerUnselectedUw min 483.3, median 512.6, max 561.7
การวิเคราะห์ระบบย่อยหลัก
PowerMetric จะบันทึกการเปลี่ยนแปลงกำลังหรือพลังงานตลอดระยะเวลาการทดสอบสำหรับหมวดหมู่กำลังที่ระบุ แต่ละหมวดหมู่ที่คุณเลือกจะแบ่ง
ออกเป็นองค์ประกอบย่อยที่วัดได้ และระบบจะเพิ่มหมวดหมู่ที่ไม่ได้เลือกไปยังเมตริก "ไม่ได้เลือก"
เอาต์พุตของเทอร์มินัลจะแมปกับการกำหนดค่าที่คุณขอ ดังนี้
powerCategoryCpuUw: ปริมาณการใช้พลังงานของ CPU ในช่วงระยะเวลาการทดสอบpowerCategoryGpuUw: ปริมาณการใช้พลังงานของ GPU ในช่วงระยะเวลาการทดสอบpowerUnselectedUw: กำลังไฟรวมที่ใช้โดยหมวดหมู่ฮาร์ดแวร์ที่พร้อมใช้งานทั้งหมดซึ่งไม่ได้ขออย่างชัดแจ้งในแผนที่การเริ่มต้น
หากต้องการป้องกันไม่ให้ข้อมูลฮาร์ดแวร์เพิ่มขึ้นอย่างผิดปกติระหว่างการเรียกใช้ ให้ล็อกความสว่างของหน้าจอ เป็นค่าคงที่ รักษาอุณหภูมิของอุปกรณ์ให้คงที่ และปิด กระบวนการพื้นหลังที่แข่งขันกันก่อนเริ่มลูป Macrobenchmark
แหล่งข้อมูลเพิ่มเติม
ดูเนื้อหา
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- สร้างโปรไฟล์พื้นฐาน {:#creating-profile-rules}
- การเขียนการทดสอบประสิทธิภาพระดับสูง
- การวิเคราะห์และการเพิ่มประสิทธิภาพการเริ่มต้นแอป {:#app-startup-analysis-optimization}