เครื่องมือการแสดงผล GPU โปรไฟล์จะระบุเวลาสัมพัทธ์ที่แต่ละขั้นของ ที่ไปป์ไลน์การแสดงผลจะใช้ในการแสดงผลเฟรมก่อนหน้า ความรู้นี้ สามารถช่วยระบุจุดคอขวดในไปป์ไลน์ เพื่อให้คุณ ทราบถึงสิ่งที่ควรปรับปรุงเพื่อปรับปรุงประสิทธิภาพการแสดงผลของแอป
หน้านี้จะอธิบายคร่าวๆ ถึงสิ่งที่เกิดขึ้นในแต่ละขั้นตอนของไปป์ไลน์ และ กล่าวถึงปัญหาที่อาจทำให้เกิดจุดคอขวดในจุดนั้น ก่อนอ่าน หน้านี้ คุณควรทำความคุ้นเคยกับข้อมูลที่แสดงใน GPU ของโปรไฟล์ การแสดงภาพ นอกจากนี้ เราขอแนะนำให้อ่านเพื่อทำความเข้าใจว่าขั้นตอนทั้งหมดทำงานร่วมกันอย่างไร วิธีการทำงานของไปป์ไลน์การแสดงผล
การนำเสนอภาพ
เครื่องมือการแสดงผล GPU ของโปรไฟล์จะแสดงขั้นตอนและเวลาที่เกี่ยวข้องใน รูปแบบของกราฟ: ฮิสโตแกรมที่มีโค้ดสี รูปที่ 1 แสดงตัวอย่างของ จอแสดงผลดังกล่าว
![](https://developer.android.com/static/topic/performance/images/bars.png?authuser=8&hl=th)
รูปที่ 1 กราฟการแสดงผล GPU ของโปรไฟล์
แต่ละส่วนของแท่งกราฟแนวตั้งแต่ละแท่งที่แสดงในการแสดงผล GPU ของโปรไฟล์ กราฟแสดงถึงขั้นตอนของไปป์ไลน์ และมีการไฮไลต์โดยใช้ สี กราฟแท่ง รูปที่ 2 แสดงกุญแจไปยังความหมายของสีแต่ละสีที่แสดง
![](https://developer.android.com/static/topic/performance/images/s-profiler-legend.png?authuser=8&hl=th)
รูปที่ 2 คำอธิบายกราฟการแสดงผล GPU ของโปรไฟล์
เมื่อเข้าใจความหมายของแต่ละสีแล้ว ซึ่งคุณกำหนดเป้าหมายแง่มุมเฉพาะ เพื่อพยายามเพิ่มประสิทธิภาพการแสดงผล
ขั้นตอนและความหมาย
ส่วนนี้จะอธิบายสิ่งที่เกิดขึ้นในแต่ละขั้นตอนที่เกี่ยวข้อง เป็นสีในรูปที่ 2 รวมถึงสาเหตุของจุดคอขวดที่ควรระวัง
การจัดการอินพุต
ขั้นตอนการจัดการอินพุตของไปป์ไลน์จะวัดระยะเวลาที่แอป ที่ใช้ในการจัดการเหตุการณ์การป้อนข้อมูล เมตริกนี้ระบุระยะเวลาที่แอป ใช้เวลาเรียกใช้โค้ดที่ถูกเรียกอันเป็นผลมาจาก Callback ของเหตุการณ์อินพุต
เมื่อกลุ่มนี้มีขนาดใหญ่
ส่วนที่มีค่าสูงในบริเวณนี้มักจะเป็นผลมาจากการทำงานมากเกินไป หรือ งานที่มีความซับซ้อนมากเกินไปที่เกิดขึ้นภายใน Callback ของเหตุการณ์เครื่องมือจัดการอินพุต เนื่องจาก Callback เหล่านี้จะเกิดขึ้นในเทรดหลักเสมอ วิธีแก้ปัญหาสำหรับ มุ่งเน้นการเพิ่มประสิทธิภาพงานโดยตรง หรือลดงานลง ชุดข้อความอื่น
นอกจากนี้ โปรดทราบว่า
RecyclerView
ที่สามารถเลื่อนได้ในระยะนี้
RecyclerView
จะเลื่อนทันทีเมื่อเรียกใช้เหตุการณ์การแตะ ด้วยเหตุนี้
เทมเพลตอาจขยายออกหรือเติมข้อมูลการดูสินค้าใหม่ ด้วยเหตุนี้ คุณจึงควร
ทำให้การดำเนินการนี้เร็วที่สุด เครื่องมือการทำโปรไฟล์ เช่น Traceview หรือ
Systrace จะช่วยคุณตรวจสอบเพิ่มเติมได้
แอนิเมชัน
ขั้นตอนภาพเคลื่อนไหวจะแสดงเวลาที่ใช้ในการประเมิน
ภาพเคลื่อนไหวที่วิ่งอยู่ในเฟรมนั้นๆ ผู้สร้างแอนิเมชันที่พบบ่อยที่สุดคือ
ObjectAnimator
,
ViewPropertyAnimator
และ
การเปลี่ยนฉาก
เมื่อกลุ่มนี้มีขนาดใหญ่
ค่าที่สูงในพื้นที่นี้มักจะเป็นผลมาจากงานที่ต้องดำเนินการ
การเปลี่ยนแปลงคุณสมบัติบางอย่างของภาพเคลื่อนไหว ตัวอย่างเช่น ภาพเคลื่อนไหวแบบสะบัด
ซึ่งจะเลื่อน ListView
หรือ
RecyclerView
,
ทำให้เกิดอัตราเงินเฟ้อและประชากรจำนวนมาก
การวัด/เลย์เอาต์
เพื่อให้ Android ดึงรายการมุมมองของคุณลงบนหน้าจอ โมเดลจะทำงาน 2 การดำเนินการที่เจาะจงในเลย์เอาต์และมุมมองในลำดับชั้นการแสดงผลของคุณ
ขั้นตอนแรก ระบบจะวัดรายการการดู ทุกมุมมองและเลย์เอาต์มี ข้อมูลที่เจาะจงที่อธิบายขนาดของวัตถุบนหน้าจอ ยอดดูบางส่วน สามารถกำหนดขนาดที่เจาะจงได้ คนอื่นๆ มีขนาดที่ปรับเปลี่ยนตามขนาด ของคอนเทนเนอร์เลย์เอาต์หลัก
ขั้นที่สอง ระบบจัดวางรายการมุมมอง เมื่อระบบคำนวณ ในขนาดที่เด็กๆ เห็น ระบบจะสามารถดำเนินการกับการจัดวาง การปรับขนาด และการวางตำแหน่งมุมมองบนหน้าจอ
ระบบจะวัดค่าและจัดเลย์เอาต์ไม่เพียงแต่สำหรับมุมมองที่จะวาดเท่านั้น แต่สำหรับลำดับชั้นระดับบนของมุมมองเหล่านั้น ไปจนถึงระดับรูท
เมื่อกลุ่มนี้มีขนาดใหญ่
ถ้าแอปของคุณใช้เวลาต่อเฟรมในบริเวณนี้นาน มักเป็นเพราะจำนวนผู้ชม จำนวนมาก ที่ต้องมี หรือปัญหาต่างๆ เช่น ภาษีซ้ำซ้อนผิดที่ในบัญชี ลำดับชั้น ในกรณีเหล่านี้ การจัดการกับประสิทธิภาพจะเกี่ยวข้องกับ การปรับปรุง ประสิทธิภาพของลำดับชั้นการแสดงผล
โค้ดที่คุณเพิ่ม
onLayout(boolean, int, int, int, int)
หรือ
วันที่ onMeasure(int, int)
ก็สามารถทำให้ประสิทธิภาพ
ปัญหา Traceview และ
Systrace ช่วยคุณตรวจสอบได้
Calltack เพื่อระบุปัญหาของโค้ดได้
วาด
ขั้นตอนการวาดจะแปลการดำเนินการการแสดงผลของมุมมอง เช่น การวาด พื้นหลังหรือข้อความการวาดเป็นลำดับคำสั่งวาดแบบเดิม ระบบจะบันทึกคำสั่งเหล่านี้ไว้ในรายการที่แสดง
แถบ "วาด" จะบันทึกระยะเวลาที่ใช้ในการบันทึกคำสั่งให้เสร็จสมบูรณ์
ไว้ในรายการที่แสดง สำหรับมุมมองทั้งหมดที่จำเป็นต้องอัปเดตบนหน้าจอ
เฟรมนี้ เวลาที่วัดจะใช้กับโค้ดทั้งหมดที่คุณเพิ่มลงใน UI
ออบเจ็กต์ในแอปของคุณ ตัวอย่างของโค้ดดังกล่าวอาจเป็น
onDraw()
,
dispatchDraw()
,
และ draw ()methods
ต่างๆ ที่อยู่ในคลาสย่อยของ
Drawable
ชั้นเรียน
เมื่อกลุ่มนี้มีขนาดใหญ่
พูดง่ายๆ ก็คือ คุณสามารถเข้าใจเมตริกนี้ว่าแสดงระยะเวลาที่ใช้ไป
เรียกใช้การเรียกทั้งหมดไปยัง
onDraw()
สำหรับข้อมูลพร็อพเพอร์ตี้ที่ไม่ถูกต้องแต่ละรายการ ช่วงเวลานี้
การวัดผลรวมถึงเวลาที่ใช้ในการส่งคำสั่งวาดให้กับเด็กและ
เนื้อหาที่ถอนออกได้ ด้วยเหตุนี้ เมื่อคุณเห็นแท่งกราฟนี้พุ่งสูงขึ้น
อาจเนื่องมาจากการที่จำนวนการดู
จำนวนมากกลายเป็นโมฆะกะทันหัน การทำให้ใช้งานไม่ได้
ก็จำเป็นต้องสร้าง
การดูใหม่" รายการที่แสดง อีกวิธีหนึ่งคือ
อาจเป็นผลมาจากการแสดงผลที่กำหนดเอง 2-3 รายการซึ่งมี
ในตรรกะที่ซับซ้อน
onDraw()
วิธี
ซิงค์/อัปโหลด
ซิงค์และ เมตริกการอัปโหลดแสดงระยะเวลาที่ใช้ในการโอน ออบเจ็กต์บิตแมปจากหน่วยความจำ CPU ไปยังหน่วยความจำ GPU ระหว่างเฟรมปัจจุบัน
เนื่องจาก CPU และ GPU มีพื้นที่ RAM ที่แตกต่างกันเนื่องจากผู้ประมวลผลข้อมูลแตกต่างกัน เพื่อการประมวลผลโดยเฉพาะ เมื่อคุณวาดบิตแมปใน Android ระบบจะ จะโอนบิตแมปไปยังหน่วยความจำ GPU ก่อนที่ GPU จะสามารถแสดงผลไปยัง บนหน้าจอ จากนั้น GPU จะแคชบิตแมปเพื่อให้ระบบไม่ต้อง โอนข้อมูลอีกครั้งเว้นแต่ว่าพื้นผิวจะถูกนำออกจากพื้นผิว GPU แคช
หมายเหตุ: ในอุปกรณ์ Lollipop ระยะนี้คือ สีม่วง
เมื่อกลุ่มนี้มีขนาดใหญ่
ทรัพยากรทั้งหมดของเฟรมต้องอยู่ในหน่วยความจำ GPU ก่อนจึงจะใช้งานได้ ที่ใช้ในการวาดเฟรม ซึ่งหมายความว่าค่าสูงสำหรับเมตริกนี้อาจหมายความว่า การโหลดทรัพยากรจำนวนมากหรือการโหลดทรัพยากรที่น้อยมาก ที่ไม่ซับซ้อน กรณีทั่วไปคือเมื่อแอปแสดงบิตแมปเดี่ยวที่ ใกล้กับขนาดหน้าจอ อีกกรณีหนึ่งคือเมื่อแอปแสดง ภาพขนาดย่อจำนวนมาก
หากต้องการย่อแท่งแผนภูมิดังกล่าว คุณสามารถใช้เทคนิคต่างๆ เช่น
- ตรวจดูให้แน่ใจว่าความละเอียดของบิตแมปไม่ได้ใหญ่กว่าขนาดของบิตแมปมากนัก จะปรากฏขึ้น เช่น แอปของคุณควรหลีกเลี่ยงการแสดงขนาด 1024x1024 เป็นรูปภาพขนาด 48x48
-
การใช้ประโยชน์จาก
prepareToDraw()
เป็นการอัปโหลดบิตแมปล่วงหน้าแบบไม่พร้อมกันก่อนขั้นตอนการซิงค์ถัดไป
คำสั่งเกี่ยวกับปัญหา
กลุ่มคำสั่งของปัญหาแสดงระยะเวลาที่ใช้ในการออกทั้งหมด คำสั่งที่จำเป็นต่อการวาดรายการบนหน้าจอ
เพื่อให้ระบบวาดรายการที่แสดงไปยังหน้าจอได้ ระบบจะส่ง คำสั่งที่จำเป็นกับ GPU โดยปกติแล้วจะดำเนินการนี้ผ่าน OpenGL ES API
กระบวนการนี้ใช้เวลาสักครู่เนื่องจากระบบแปลงขั้นสุดท้าย และการตัดคลิปสำหรับแต่ละคำสั่งก่อนที่จะส่งคำสั่งไปยัง GPU ข้อมูลเพิ่มเติม จึงเกิดขึ้นในฝั่ง GPU ซึ่งคำนวณคำสั่งสุดท้าย เหล่านี้ รวมถึงการแปลงขั้นสุดท้ายและการคลิปเพิ่มเติม
เมื่อกลุ่มนี้มีขนาดใหญ่
เวลาที่ใช้ในขั้นตอนนี้จะเป็นการวัดโดยตรงของความซับซ้อนและ จำนวนรายการที่แสดงซึ่งระบบแสดงผลใน เฟรม ตัวอย่างเช่น มีการวาดจำนวนมาก โดยเฉพาะในกรณีที่ มีค่าใช้จ่ายเริ่มต้นเล็กน้อยสำหรับการวาดพื้นฐานแต่ละครั้ง ซึ่งอาจเพิ่มสูงเกินจริงในครั้งนี้ เช่น
Kotlin
for (i in 0 until 1000) { canvas.drawPoint() }
Java
for (int i = 0; i < 1000; i++) { canvas.drawPoint() }
มีค่าใช้จ่ายในการออกสูงกว่ามาก
Kotlin
canvas.drawPoints(thousandPointArray)
Java
canvas.drawPoints(thousandPointArray);
การออกคำสั่งกับการออกคำสั่งไม่ได้เป็นแบบ 1:1 เสมอไป ที่วาดรายการแสดงขึ้นมาจริงๆ ซึ่งต่างจาก Issue Commands ซึ่งจะบันทึกระยะเวลาที่ใช้ในการส่งคำสั่งวาดไปยัง GPU เมตริกวาดแสดงเวลาที่ใช้ในการบันทึกจำนวนเงินที่ออก ลงในรายการที่แสดง
ความแตกต่างนี้เกิดขึ้นเนื่องจากรายการที่แสดงมีการแคชโดย ระบบในทุกที่ที่เป็นไปได้ ดังนั้นจึงมีสถานการณ์ที่ การเลื่อน การเปลี่ยนรูปแบบ หรือภาพเคลื่อนไหวกําหนดให้ระบบส่งจอแสดงผลอีกครั้ง แต่ไม่จำเป็นต้องสร้างใหม่ จับภาพภาพวาดใหม่ ตั้งแต่เริ่มต้น ดังนั้นคุณจึงจะเห็นสถานะ "ปัญหา" คำสั่ง" แต่ไม่เห็นแถบ Drawคำสั่ง สูง
ประมวลผล/สลับบัฟเฟอร์
เมื่อ Android ส่งรายการที่แสดงทั้งหมดไปยัง GPU เสร็จแล้ว ระบบจะออกคำสั่งสุดท้ายหนึ่งรายการเพื่อบอกไดรเวอร์กราฟิกว่า กับเฟรมปัจจุบันแล้ว ณ จุดนี้ คนขับสามารถนำเสนอ รูปภาพที่อัปเดตแล้วลงบนหน้าจอ
เมื่อกลุ่มนี้มีขนาดใหญ่
สิ่งสำคัญคือต้องเข้าใจว่า GPU ทำงานควบคู่กับ CPU ปัญหาระบบ Android จะวาดคำสั่งไปยัง GPU จากนั้นไปที่ งานถัดไป GPU อ่านคำสั่งดึงเหล่านั้นจากคิวและกระบวนการ ให้พวกเขา
ในสถานการณ์ที่คำสั่งเกี่ยวกับปัญหา CPU เร็วกว่า GPU มีการใช้งาน คิวการสื่อสารระหว่างผู้ประมวลผลข้อมูลอาจกลายเป็น เต็มรูปแบบ เมื่อเกิดกรณีนี้ขึ้น CPU จะบล็อกและรอจนกว่าจะมีพื้นที่ใน เพื่อวางคำสั่งถัดไป สถานะคิวเต็มนี้เกิดขึ้นบ่อยในช่วง สลับบัฟเฟอร์เนื่องจาก ณ จุดนั้น ค่าของทั้งเฟรม ส่งคำสั่งแล้ว
กุญแจสำคัญในการบรรเทาปัญหานี้คือการลดความซับซ้อนของงานที่เกิดขึ้น บน GPU ในลักษณะเดียวกับสิ่งที่คุณจะทำกับ "คำสั่งของปัญหา"
เบ็ดเตล็ด
นอกจากเวลาที่ต้องใช้ไปกับระบบการแสดงผลในการทำงานแล้ว มีงานอีกชุดหนึ่งเกิดขึ้นในเทรดหลัก กับการแสดงภาพ ระบบจะรายงานเวลาที่ใช้เวลาทำงานนี้เป็น เวลาเบ็ดเตล็ด โดยทั่วไปแล้ว เวลาเบ็ดเตล็ดแสดงถึงงานที่อาจเกิดขึ้น บนเธรด UI ระหว่างเฟรมการแสดงผล 2 เฟรมติดต่อกัน
เมื่อกลุ่มนี้มีขนาดใหญ่
หากค่านี้สูง แสดงว่าแอปอาจมี Callback, Intent หรือ งานอื่นๆ ที่ควรจะเกิดขึ้นในชุดข้อความอื่น เครื่องมือ เช่น เมธอด tracing หรือ Systrace จะช่วยให้ การมองเห็นงานที่กำลังดำเนินอยู่ เทรดหลัก ข้อมูลนี้จะช่วยให้คุณกำหนดเป้าหมายการปรับปรุงประสิทธิภาพได้