เครื่องมือการแสดงผล GPU ตามโปรไฟล์จะระบุเวลาสัมพัทธ์ที่แต่ละระยะของไปป์ไลน์การแสดงผลใช้ในการแสดงผลเฟรมก่อนหน้า ความรู้นี้จะช่วยคุณระบุจุดคอขวดในไปป์ไลน์ เพื่อให้คุณทราบว่าควรเพิ่มประสิทธิภาพสิ่งใดเพื่อปรับปรุงประสิทธิภาพการแสดงผลของแอป
หน้านี้จะอธิบายถึงสิ่งที่เกิดขึ้นในแต่ละขั้นตอนของไปป์ไลน์โดยสรุป และอธิบายถึงปัญหาที่อาจทำให้เกิดจุดคอขวดในจุดนั้น ก่อนอ่านหน้านี้ คุณควรทำความคุ้นเคยกับข้อมูลที่แสดงในโปรไฟล์การแสดงผล GPU นอกจากนี้ คุณอาจต้องทบทวนวิธีการทำงานของไปป์ไลน์การแสดงผลเพื่อให้เข้าใจว่าแต่ละระยะทำงานร่วมกันอย่างไร
การนำเสนอด้วยภาพ
เครื่องมือการแสดงผล GPU โปรไฟล์จะแสดงขั้นตอนและเวลาที่เกี่ยวข้องในรูปแบบของกราฟ ซึ่งเป็นฮิสโตแกรมที่มีโค้ดสี รูปที่ 1 แสดงตัวอย่าง ของจอแสดงผลดังกล่าว
แต่ละส่วนของแท่งแนวตั้งแต่ละแท่งที่แสดงในกราฟการแสดงผล GPU ของโปรไฟล์แสดงถึงขั้นของไปป์ไลน์และถูกไฮไลต์โดยใช้สีที่เจาะจงในกราฟแท่ง รูปที่ 2 แสดงคีย์ความหมายของสีที่แสดงแต่ละสี
เมื่อเข้าใจแล้วว่าแต่ละสีมีความหมายอย่างไร คุณสามารถกำหนดเป้าหมายเฉพาะด้านของแอปเพื่อพยายามเพิ่มประสิทธิภาพการแสดงผลได้
ขั้นตอนและความหมาย
ส่วนนี้อธิบายสิ่งที่เกิดขึ้นในแต่ละระยะที่ตรงกับสีในรูปที่ 2 รวมถึงสาเหตุที่ควรระวังจุดคอขวด
การจัดการอินพุต
ขั้นตอนการจัดการอินพุตของไปป์ไลน์จะวัดระยะเวลาที่แอปใช้ในการจัดการเหตุการณ์อินพุต เมตริกนี้ระบุระยะเวลาที่แอปใช้ในการเรียกใช้โค้ดที่เรียกเป็นผลมาจากการเรียกกลับเหตุการณ์อินพุต
เมื่อกลุ่มนี้มีขนาดใหญ่
ค่าที่สูงในพื้นที่นี้มักจะเป็นผลมาจากงานมากเกินไปหรือการทำงานที่ซับซ้อนเกินไปที่เกิดขึ้นภายใน Callback ของเหตุการณ์เครื่องมือจัดการอินพุต เนื่องจากระบบจะเรียกใช้การเรียกกลับเหล่านี้ในเธรดหลักเสมอ วิธีแก้ปัญหานี้จึงมุ่งเน้นที่การเพิ่มประสิทธิภาพงานโดยตรง หรือส่งงานไปยังเธรดอื่น
นอกจากนี้ โปรดทราบว่า
RecyclerView
การเลื่อนอาจเกิดขึ้นในระยะนี้
RecyclerView
เลื่อนทันทีที่ใช้งานเหตุการณ์การสัมผัส ด้วยเหตุนี้ ระบบจึงอาจเพิ่มหรือป้อนข้อมูลยอดดูรายการใหม่ ด้วยเหตุนี้ จึงเป็นสิ่งสำคัญ
ที่คุณจะต้องทำให้การดำเนินการนี้เร็วที่สุด เครื่องมือการทำโปรไฟล์ เช่น Traceview หรือ Systrace จะช่วยให้คุณตรวจสอบเพิ่มเติมได้
แอนิเมชัน
ช่วงภาพเคลื่อนไหวจะแสดงเวลาที่ใช้ในการประเมินภาพเคลื่อนไหวทั้งหมดที่อยู่ในเฟรมนั้น ผู้สร้างแอนิเมชันที่พบบ่อยที่สุดคือ
ObjectAnimator
,
ViewPropertyAnimator
และ
ทรานซิชัน
เมื่อกลุ่มนี้มีขนาดใหญ่
ค่าสูงในพื้นที่นี้มักเป็นผลมาจากงานที่ดำเนินการเนื่องจากการเปลี่ยนแปลงพร็อพเพอร์ตี้บางอย่างของภาพเคลื่อนไหว ตัวอย่างเช่น ภาพเคลื่อนไหวแบบขว้าง ซึ่งจะเลื่อน ListView
หรือ RecyclerView
ก็ทําให้อัตราเงินเฟ้อและประชากรเพิ่มขึ้นอย่างมาก
การวัด/เลย์เอาต์
เพื่อให้ Android วาดรายการในมุมมองบนหน้าจอได้ การดำเนินการนั้นจะดำเนินการ 2 อย่างในเลย์เอาต์และมุมมองในลำดับชั้นการแสดงผล
ขั้นแรก ระบบจะวัดรายการการดู มุมมองและเลย์เอาต์ทุกรายการมีข้อมูลที่เฉพาะเจาะจงซึ่งอธิบายขนาดของวัตถุบนหน้าจอ มุมมองบางรายการอาจมีขนาดที่เจาะจง ในขณะที่มุมมองอื่นๆ มีขนาดที่ปรับตามขนาดของคอนเทนเนอร์เลย์เอาต์หลัก
ขั้นที่สอง ระบบจัดวางรายการมุมมอง เมื่อระบบคำนวณขนาดของมุมมองสำหรับเด็กแล้ว ก็จะดำเนินการต่อด้วยเลย์เอาต์ การปรับขนาด และการวางตำแหน่งมุมมองบนหน้าจอ
ระบบจะวัดและจัดเลย์เอาต์ไม่เพียงแต่สำหรับมุมมองที่จะวาดเท่านั้น แต่ยังสำหรับลำดับชั้นระดับบนของมุมมองเหล่านั้นไปจนถึงมุมมองรูทด้วย
เมื่อกลุ่มนี้มีขนาดใหญ่
หากแอปใช้เวลานานมากต่อเฟรมในส่วนนี้ สาเหตุมักเกิดจากปริมาณมุมมองจำนวนมากที่ต้องจัดวาง หรือปัญหาต่างๆ เช่น การเรียกเก็บภาษีซ้ำในตำแหน่งที่ไม่ถูกต้องในลําดับชั้น ไม่ว่าในกรณีใด การจัดการประสิทธิภาพก็เกี่ยวข้องกับการปรับปรุงประสิทธิภาพของลําดับชั้นมุมมอง
รหัสที่คุณเพิ่มลงใน onLayout(boolean, int, int, int, int)
หรือ onMeasure(int, int)
อาจทำให้เกิดปัญหาด้านประสิทธิภาพได้เช่นกัน Traceview และ Systrace ช่วยให้คุณตรวจสอบกองคิวการเรียกเพื่อระบุปัญหาที่โค้ดอาจพบได้
วาด
ระยะวาดจะแปลการดำเนินการแสดงผลของมุมมอง เช่น การวาดพื้นหลังหรือการวาดข้อความ เป็นลำดับคำสั่งวาดแบบดั้งเดิม ระบบจะบันทึกคําสั่งเหล่านี้ไว้ในรายการที่แสดง
แถบวาดจะบันทึกระยะเวลาที่ใช้ในการบันทึกคําสั่งลงในรายการการแสดงผลสําหรับมุมมองทั้งหมดที่ต้องอัปเดตบนหน้าจอในเฟรมนี้ เวลาที่วัดจะใช้กับโค้ดทั้งหมดที่คุณเพิ่มลงในออบเจ็กต์ 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 เพื่อให้วาดรายการที่แสดงบนหน้าจอ ซึ่งโดยปกติแล้วจะดำเนินการนี้ผ่าน API OpenGL ES
กระบวนการนี้ใช้เวลาสักระยะหนึ่ง เนื่องจากระบบทำการเปลี่ยนรูปแบบขั้นสุดท้ายและตัดข้อความสำหรับแต่ละคำสั่งก่อนที่จะส่งคำสั่งไปยัง 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 เสมอไป เมตริก Draw จะแสดงเวลาที่ใช้ในการบันทึกคำสั่งที่ออกลงในรายการที่แสดง ซึ่งแตกต่างจากคำสั่งปัญหาที่บันทึกระยะเวลาในการส่งคำสั่งวาดไปยัง GPU
ความแตกต่างนี้เกิดขึ้นเนื่องจากระบบแคชรายการที่แสดง เมื่อเป็นไปได้ ด้วยเหตุนี้ จึงมีบางกรณีที่การเลื่อน การเปลี่ยนรูปแบบ หรือภาพเคลื่อนไหวทำให้ระบบต้องส่งรายการที่แสดงอีกครั้ง แต่ไม่จำเป็นต้องสร้างใหม่ทั้งหมด นั่นคือไม่ต้องบันทึกคำสั่งวาดภาพใหม่ตั้งแต่ต้น คุณจึงเห็นแถบ "ออกคำสั่ง" สูงโดยที่ไม่เห็นแถบวาดคำสั่งสูง
ประมวลผล/สลับบัฟเฟอร์
เมื่อ Android ส่งรายการการแสดงผลทั้งหมดไปยัง GPU แล้ว ระบบจะออกคำสั่งสุดท้ายเพื่อแจ้งให้ไดรเวอร์กราฟิกทราบว่าแสดงเฟรมปัจจุบันเสร็จแล้ว เมื่อถึงจุดนี้ โปรแกรมควบคุมจึงแสดงภาพเวอร์ชันอัปเดตบนหน้าจอได้
เมื่อกลุ่มนี้มีขนาดใหญ่
โปรดเข้าใจว่า GPU ทำงานควบคู่กับ CPU ปัญหาเกี่ยวกับระบบ Android จะวาดคำสั่งไปยัง GPU แล้วย้ายไปยังงานถัดไป GPU จะอ่านคำสั่งดึงเหล่านั้นจากคิวและประมวลผลคำสั่งเหล่านั้น
ในกรณีที่ปัญหาของ CPU มีคำสั่งเร็วกว่าที่ GPU ใช้ไป คิวการสื่อสารระหว่างตัวประมวลผลอาจเต็มได้ เมื่อเกิดกรณีนี้ขึ้น CPU จะบล็อกและรอจนกว่าจะมีพื้นที่ในคิวเพื่อวางคำสั่งถัดไป สถานะคิวเต็มนี้เกิดขึ้นบ่อยครั้งในช่วงสลับบัฟเฟอร์ เพราะ ณ เวลานั้น มีการส่งคำสั่งของทั้งเฟรม
หัวใจสำคัญในการบรรเทาปัญหานี้คือลดความซับซ้อนของงานที่ดำเนินการใน GPU ในลักษณะเดียวกับที่คุณจะทำในขั้นตอน "ออกคำสั่ง"
เบ็ดเตล็ด
นอกจากเวลาที่ระบบใช้ทำงานแล้ว ยังมีงานอีกชุดหนึ่งที่เกิดขึ้นในเทรดหลักและไม่เกี่ยวข้องกับการแสดงผล ระบบจะรายงานเวลาที่ใช้ในการทำงานนี้ว่าเป็นเวลาอื่นๆ โดยทั่วไปแล้ว เวลาอื่นๆ จะแสดงถึงงานที่อาจเกิดขึ้นในเธรด UI ระหว่างเฟรมการแสดงผล 2 เฟรมติดต่อกัน
เมื่อกลุ่มนี้มีขนาดใหญ่
หากค่านี้สูง แสดงว่าแอปของคุณอาจมีคอลแบ็ก อินเทนต์ หรืองานอื่นๆ ที่ควรเกิดขึ้นในเธรดอื่น เครื่องมือต่างๆ เช่น การติดตามเมธอดหรือ Systrace จะช่วยให้คุณเห็นภาพงานที่กำลังทำงานอยู่ในเธรดหลัก ข้อมูลนี้จะช่วยให้คุณมุ่งปรับปรุงประสิทธิภาพได้