เมตริกเป็นข้อมูลประเภทหลักที่ดึงมาจากการเปรียบเทียบ ระบบจะส่งพารามิเตอร์เหล่านี้ไปยังฟังก์ชัน 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 แสดงถึงส่วนการติดตามที่กำหนดเองซึ่งกำหนดไว้ภายในเลเยอร์รายการที่ Composable โดยใช้ Wrapper บล็อก trace(sectionName) { ... } ของ Kotlin มาตรฐาน หากต้องการระบุข้อมูลสำหรับ
TraceSectionMetric คุณต้องรวมคอมโพเนนต์ UI เป้าหมายไว้ในฐานของโค้ดเวอร์ชันที่ใช้งานจริงของแอปพลิเคชันด้วย Wrapper บล็อก trace ของรันไทม์ Jetpack มาตรฐาน ดังนี้
@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: ระยะเวลาตั้งแต่ที่ระบบได้รับ Intent การเปิดแอปจนถึงเวลาที่แสดงผลเฟรมแรกของหน้าจอปลายทางtimeToFullDisplayMs: ระยะเวลาตั้งแต่ที่ระบบได้รับ Intent การเปิดแอปจนถึงเวลาที่แอปรายงานว่าวาดเสร็จสมบูรณ์โดยใช้กลไกการรายงานภายในแพลตฟอร์ม การวัดจะหยุดลงเมื่อการแสดงผลเฟรมแรกเสร็จสมบูรณ์หลังจากหรือมีสัญญาณที่วาดเสร็จสมบูรณ์
StartupTimingMetric จะแสดงค่าต่ำสุด ค่ามัธยฐาน และค่าสูงสุดจากการทำซ้ำการเริ่มต้นระบบ หากต้องการประเมินการปรับปรุงการเริ่มต้นระบบ ให้มุ่งเน้นที่ค่ามัธยฐานเสมอ เนื่องจากค่าดังกล่าวจะให้ค่าประมาณที่ดีที่สุดของเวลาเริ่มต้นระบบของผู้ใช้ทั่วไป
ในสถาปัตยกรรมที่ใช้ Compose เป็นหลัก อย่าพยายามเรียกใช้ activity.reportFullyDrawn ด้วยตนเอง แต่ให้ใช้ยูทิลิตีแบบอะซิงโครนัสที่ปลอดภัยสำหรับ Compose อย่าง ReportDrawn, ReportDrawnWhen หรือ ReportDrawnAfter ภายใน Composable ของหน้าจอเพื่อส่งสัญญาณไปยัง Macrobenchmark โดยอัตโนมัติเมื่อข้อมูลเครือข่ายแบบอะซิงโครนัสหรือสถานะ UI ที่ซับซ้อนแสดงผลเสร็จแล้ว
ดูข้อมูลเพิ่มเติมเกี่ยวกับการวิเคราะห์และการเพิ่มประสิทธิภาพการเริ่มต้นได้ที่เวลาเริ่มต้นของแอป
FrameTimingMetric
FrameTimingMetric จะบันทึกข้อมูลเวลาที่แน่นอนจากเฟรมที่สร้างโดยเส้นทางการเปรียบเทียบ เช่น การเลื่อนรายการหรือภาพเคลื่อนไหวเลย์เอาต์ของ UI ที่ซับซ้อน และแสดงผลค่าการวินิจฉัยต่อไปนี้
frameOverrunMs: ระยะเวลาที่เฟรมหนึ่งๆ พลาดกำหนดเวลา ตัวเลขที่เป็นบวกแสดงถึงเฟรมที่หายไปซึ่งมาพร้อมกับภาพกระตุกหรือภาพค้างที่มองเห็นได้ ตัวเลขติดลบแสดงให้เห็นว่าเฟรมเสร็จเร็วขึ้นเท่าใดเมื่อเทียบกับกำหนดเวลาของฮาร์ดแวร์ระบบย่อย หมายเหตุ: เมตริกนี้ใช้ได้เฉพาะใน Android 12 (ระดับ API 31) ขึ้นไปเท่านั้นframeDurationCpuMs: ระยะเวลาที่ใช้ในการสร้างเฟรมบน CPU ทั้งในเธรด UI ของแอปพลิเคชันหลักและRenderThreadของ Compose
ระบบจะรวบรวมการวัดเหล่านี้ในการกระจายเปอร์เซ็นไทล์ที่ 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 คุณสามารถแสดงฟังก์ชันที่ประกอบกันได้แต่ละรายการในกราฟการติดตามของระบบโดยไม่ต้องเขียน Wrapper การติดตามด้วยตนเองด้วยการเปิดใช้การติดตามการคอมโพส
แม้ว่าการเพิ่มทรัพยากร Dependency androidx.compose.runtime:runtime-tracing ลงในแอปพลิเคชันเป้าหมายจะเพียงพอสำหรับการติดตามเครื่องมือวิเคราะห์ด้วยตนเอง แต่การบันทึกการติดตามเหล่านี้แบบเป็นโปรแกรมภายในการเรียกใช้ Macrobenchmark ต้องมีการกำหนดค่าเพิ่มเติมภายในโมดูลการเปรียบเทียบ
ดูวิธีการตั้งค่าทั้งหมดได้ที่บันทึกการติดตามด้วย Jetpack Macrobenchmark
PowerMetric
PowerMetric จะบันทึกการเปลี่ยนแปลงของกำลังหรือพลังงานตลอดระยะเวลาที่เรียกใช้ Macrobenchmark หมวดหมู่ที่เลือกแต่ละหมวดหมู่จะแยกย่อยออกเป็นส่วนประกอบฮาร์ดแวร์ที่วัดได้ ส่วนหมวดหมู่ที่ไม่ได้เลือกจะจัดกลุ่มไว้ในที่เก็บ "ไม่ได้เลือก"
ข้อกำหนดด้านฮาร์ดแวร์: เมตริกเหล่านี้จะวัดการใช้ทรัพยากรทั้งระบบแทนการคำนวณต่อแอป ด้วยเหตุนี้ การเก็บรวบรวมข้อมูลจึงจำกัดเฉพาะอุปกรณ์จริงอย่าง 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}
- การเขียน Macrobenchmark
- การวิเคราะห์และการเพิ่มประสิทธิภาพการเริ่มต้นแอป {:#app-startup-analysis-optimization}