กรณีศึกษา: ทีม Gmail Wear OS ปรับปรุงการเริ่มต้นแอปได้ 50%

การเริ่มต้นแอปแสดงถึงความประทับใจแรกของผู้ใช้ที่มีต่อแอป และผู้ใช้ไม่ชอบรอ ดังนั้นคุณต้องตรวจสอบว่าแอปของคุณเริ่มทำงานได้อย่างรวดเร็ว หากต้องการแสดงให้คุณเห็น ว่าทีมพัฒนาแอปในชีวิตจริงค้นหาและวินิจฉัยปัญหาเกี่ยวกับการเริ่มต้นแอปของตนอย่างไร นี่คือสิ่งที่ทีม Gmail Wear OS ทำ

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

บันทึกการติดตามและดูการเริ่มต้นแอป

หากต้องการเริ่มวิเคราะห์ ให้บันทึกการติดตามที่มี การเริ่มต้นแอปเพื่อตรวจสอบอย่างละเอียดใน Perfetto หรือ Android Studio กรณีศึกษา นี้ใช้ Perfetto เนื่องจากจะแสดงให้เห็นสิ่งที่เกิดขึ้นในระบบ ของอุปกรณ์ นอกเหนือจากแอปของคุณ เมื่ออัปโหลดการติดตามใน Perfetto การติดตามจะมีลักษณะดังนี้

รูปที่ 1 มุมมองเริ่มต้นของร่องรอยใน Perfetto

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

แถวการเริ่มต้นแอป Android ที่ไฮไลต์ตัวเลือกในการปักหมุด
รูปที่ 2 ปักหมุดเมตริกที่กําหนดเองของเวลาเริ่มต้นแอป Android ไว้ที่ด้านบนของแดชบอร์ดเพื่อให้วิเคราะห์ได้ง่ายขึ้น

โปรดทราบว่าเมตริกการเริ่มต้นแอป Android แสดงถึง เวลาในการแสดงผลครั้งแรก แม้ว่าคุณจะใช้ reportFullyDrawn() ก็ตาม หากต้องการระบุเวลาที่ใช้ในการแสดงผลครบถ้วน ให้ค้นหา reportFullyDrawn() ในช่องค้นหาของ Perfetto

ตรวจสอบเทรดหลัก

ก่อนอื่น ให้ตรวจสอบว่าเกิดอะไรขึ้นในเทรดหลัก เธรดหลัก มีความสำคัญมากเนื่องจากมักเป็นที่ที่การแสดงผล UI ทั้งหมดเกิดขึ้น เมื่อ ถูกบล็อก จะไม่มีการวาดเกิดขึ้นและแอปจะดูเหมือนค้าง ดังนั้น คุณจึงต้องตรวจสอบว่าไม่มีการดำเนินการที่ใช้เวลานานในเทรดหลัก

หากต้องการค้นหาเทรดหลัก ให้ค้นหาแถวที่มีชื่อแพ็กเกจของแอป แล้วขยาย แถวนั้น 2 แถวที่มีชื่อเดียวกับแพ็กเกจ (โดยปกติคือ 2 แถวแรกในส่วน) แสดงถึงเทรดหลัก จากแถวเธรดหลัก 2 แถว แถวแรกแสดงสถานะ CPU และแถวที่ 2 แสดง Tracepoint ปักหมุด แถวของ 2 เธรดหลักไว้ใต้เมตริกการเริ่มต้นแอป Android

ปักหมุดการเริ่มต้นแอป Android และแถวเทรดหลัก
รูปที่ 3 ปักหมุดแถวของเทรดหลักไว้ใต้เมตริกที่กําหนดเองของ Android App Startups เพื่อช่วยในการวิเคราะห์

เวลาที่ใช้ในสถานะที่เรียกใช้ได้และการแย่งชิง CPU

หากต้องการดูภาพรวมกิจกรรมของ CPU ระหว่างการเริ่มต้นแอป ให้ลากเคอร์เซอร์ เหนือเทรดหลักเพื่อบันทึกช่วงเวลาเริ่มต้นแอป แผงสถานะเธรดที่ปรากฏจะแสดงระยะเวลาทั้งหมดที่ใช้ในสถานะ CPU แต่ละสถานะภายในช่วงเวลาที่เลือก

ดูเวลาที่ใช้ในสถานะRunnable เมื่อเธรดอยู่ในRunnable สถานะ เธรดจะพร้อมทำงานแต่ไม่มีการกำหนดเวลาให้ทำงาน ซึ่งอาจ บ่งบอกว่าอุปกรณ์ทำงานหนักและไม่สามารถกำหนดเวลา งานที่มีลำดับความสำคัญสูงได้ แอปที่ผู้ใช้มองเห็นซึ่งอยู่ด้านบนสุดจะมีลำดับความสำคัญสูงสุดในการ จัดกำหนดการ ดังนั้นเทรดหลักที่ไม่ได้ใช้งานมักจะบ่งบอกว่ากระบวนการที่เข้มข้น ภายในแอป เช่น การแสดงภาพเคลื่อนไหว กำลังแข่งขันกับเทรดหลัก เพื่อเวลา CPU

เทรดหลักไฮไลต์ด้วยเวลาทั้งหมดในสถานะต่างๆ ในแผงสถานะเทรด
รูปที่ 4 ประเมินเวลาสัมพัทธ์ในสถานะ Runnable ถึง Running เพื่อให้ทราบเบื้องต้นว่ามีการแย่งชิง CPU มากน้อยเพียงใด

ยิ่งอัตราส่วนของเวลาในสถานะ Runnable ต่อเวลาในสถานะ Running สูงขึ้น ก็ยิ่งมีแนวโน้มที่จะเกิดการแย่งชิง CPU เมื่อตรวจสอบปัญหาด้านประสิทธิภาพด้วยวิธีนี้ ให้มุ่งเน้นที่เฟรมที่ทำงานนานที่สุดก่อน แล้วค่อยๆ ดูเฟรมที่ทำงานสั้นลง

เมื่อวิเคราะห์เวลาที่ใช้ในRunnableสถานะ ให้พิจารณาฮาร์ดแวร์ของอุปกรณ์ เนื่องจากแอปที่แสดงทำงานบนอุปกรณ์ที่สวมใส่ได้ซึ่งมี CPU 2 ตัว เราจึงคาดว่าเวลาที่ใช้ในสถานะ Runnable จะนานขึ้น และ CPU จะมีการแย่งชิงกับกระบวนการอื่นๆ มากขึ้นกว่าในกรณีที่เราดูอุปกรณ์ที่มี CPU มากกว่า แม้ว่าแอปโทรศัพท์ทั่วไปจะใช้เวลาในสถานะ Runnable นานกว่าที่คาดไว้ แต่ก็อาจเข้าใจได้ในบริบทของอุปกรณ์ที่สวมใส่ได้

เวลาที่ใช้ใน OpenDexFilesFromOat*

ตอนนี้ให้ตรวจสอบเวลาที่ใช้ใน OpenDexFilesFromOat* ในการติดตาม เหตุการณ์นี้จะเกิดขึ้นพร้อมกับสไลซ์ bindApplication สไลซ์นี้แสดงเวลาที่ใช้ในการอ่านไฟล์ DEX ของแอปพลิเคชัน

ธุรกรรมสมุดบัญชีที่ถูกบล็อก

จากนั้นตรวจสอบธุรกรรมของ Binder ธุรกรรม Binder แสดงถึงการเรียกใช้ระหว่างไคลเอ็นต์กับเซิร์ฟเวอร์ ในกรณีนี้ แอป (ไคลเอ็นต์) จะเรียกใช้ระบบ Android (เซิร์ฟเวอร์) ด้วย binder transaction และเซิร์ฟเวอร์จะตอบกลับด้วย binder reply ตรวจสอบว่าแอปไม่ได้ทำธุรกรรม Binder ที่ไม่จำเป็น ในระหว่างการเริ่มต้น เนื่องจากจะเพิ่มความเสี่ยงของการแย่งชิง CPU หากทำได้ ให้ เลื่อนงานที่เกี่ยวข้องกับการเรียก Binder ไปเป็นหลังจากช่วงเริ่มต้นของแอป หากคุณต้องทำธุรกรรม Binder โปรดตรวจสอบว่าธุรกรรมดังกล่าวใช้เวลาไม่นานกว่าอัตราการรีเฟรช Vsync ของอุปกรณ์

ธุรกรรมการผูกครั้งแรกซึ่งมักจะเกิดขึ้นพร้อมกับActivityThreadMainดูเหมือนจะใช้เวลานานพอสมควรในกรณีนี้ หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่อาจเกิดขึ้น ให้ทำตามขั้นตอนต่อไปนี้

  1. หากต้องการดูการตอบกลับของ Binder ที่เชื่อมโยงและดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีจัดลําดับความสําคัญของธุรกรรม Binder ให้คลิกส่วนธุรกรรม Binder ที่ สนใจ
  2. หากต้องการดูการตอบกลับของ Binder ให้ไปที่แผงการเลือกปัจจุบัน แล้วคลิก การตอบกลับของ Binder ในส่วนเธรดที่ติดตาม ฟิลด์เธรด ยังบอกเธรดที่การตอบกลับของ Binder เกิดขึ้นด้วย หากคุณต้องการ ไปยังเธรดนั้นด้วยตนเอง โดยจะอยู่ในกระบวนการที่แตกต่างกัน เส้นจะปรากฏขึ้น ซึ่งเชื่อมต่อธุรกรรมของ Binder กับการตอบกลับ

    เส้นจะเชื่อมต่อการเรียกใช้ Binder กับการตอบกลับ
    รูปที่ 5 ระบุธุรกรรม Binder ที่เกิดขึ้นระหว่างการเริ่มต้นแอปและประเมินว่าคุณสามารถเลื่อนธุรกรรมเหล่านั้นได้หรือไม่
  3. หากต้องการดูว่าเซิร์ฟเวอร์ระบบจัดการธุรกรรม Binder นี้อย่างไร ให้ปักหมุดเธรด CPU 0 และ CPU 1 ไว้ที่ด้านบนของหน้าจอ

  4. ค้นหากระบวนการของระบบที่จัดการการตอบกลับ Binder โดยค้นหา Slice ที่มีชื่อเธรดการตอบกลับ Binder ซึ่งในกรณีนี้คือ "Binder:687_11 [2542]" คลิกกระบวนการของระบบที่เกี่ยวข้องเพื่อดูข้อมูลเพิ่มเติม เกี่ยวกับธุรกรรมการผูก

ดูที่กระบวนการของระบบที่เชื่อมโยงกับธุรกรรม Binder ที่ สนใจซึ่งเกิดขึ้นใน CPU 0

กระบวนการของระบบที่มีสถานะสิ้นสุดเป็น "Runnable (Preempted)"
รูปที่ 6 กระบวนการของระบบอยู่ในสถานะ Runnable (Preempted) ซึ่งบ่งบอกว่าระบบ ทำงานช้าลง

สถานะสิ้นสุดระบุว่า Runnable (Preempted) ซึ่งหมายความว่ากระบวนการ ล่าช้าเนื่องจาก CPU กำลังทำอย่างอื่น หากต้องการดูว่าอะไรทำให้เกิดการขัดจังหวะ ให้ขยายแถวเหตุการณ์ Ftrace ในแท็บ Ftrace Events ที่พร้อมใช้งาน ให้เลื่อนดูและค้นหาเหตุการณ์ที่เกี่ยวข้อง กับเธรด Binder ที่สนใจ "Binder:687_11 [2542]" ในช่วงเวลาที่ระบบขัดจังหวะกระบวนการของระบบ มีเหตุการณ์เซิร์ฟเวอร์ของระบบ 2 รายการที่รวมอาร์กิวเมนต์ "decon" ซึ่งหมายความว่าเหตุการณ์ดังกล่าวเกี่ยวข้องกับตัวควบคุมการแสดงผล ซึ่งฟังดูสมเหตุสมผลเนื่องจากตัวควบคุมการแสดงผลจะวางเฟรมบนหน้าจอ ซึ่งเป็นงานที่สำคัญ ในกรณีนี้ ให้ปล่อยกิจกรรมไว้ตามเดิม

เหตุการณ์ FTrace ที่เชื่อมโยงกับธุรกรรม Binder ที่สนใจจะได้รับการไฮไลต์
รูปที่ 7 เหตุการณ์ FTrace บ่งชี้ว่าธุรกรรม Binder ล่าช้าเนื่องจากเหตุการณ์ของตัวควบคุมการแสดงผล

กิจกรรม JIT

หากต้องการตรวจสอบกิจกรรมการคอมไพล์แบบทันที (JIT) ให้ขยายกระบวนการที่เป็นของแอป ค้นหาแถว "Jit thread pool" 2 แถว แล้วปักหมุดไว้ที่ด้านบนของมุมมอง เนื่องจากแอปนี้ได้รับประโยชน์จากโปรไฟล์พื้นฐานในระหว่างการเริ่มต้นแอป จึงมีกิจกรรม JIT น้อยมากจนกว่าจะมีการวาดเฟรมแรก ซึ่งระบุโดย การสิ้นสุดการเรียกใช้ Choreographer.doFrame ครั้งแรก อย่างไรก็ตาม โปรดสังเกตสาเหตุของการเริ่มต้นที่ช้า JIT compiling void ซึ่งบ่งชี้ว่ากิจกรรมของระบบที่เกิดขึ้น ระหว่าง Tracepoint ที่ติดป้ายกำกับ Application creation ทำให้เกิดกิจกรรม JIT ในเบื้องหลังจำนวนมาก หากต้องการแก้ไขปัญหานี้ ให้เพิ่มเหตุการณ์ที่เกิดขึ้นหลังจากวาดเฟรมแรกไม่นานลงใน Baseline Profile โดยขยายการรวบรวมโปรไฟล์ไปยังจุดที่แอปพร้อมใช้งาน ในหลายๆ กรณี คุณสามารถ ทำได้โดยการเพิ่มบรรทัดที่ส่วนท้ายของการรวบรวม Baseline Profile การทดสอบ Macrobenchmark ที่รอให้วิดเจ็ต UI ที่เฉพาะเจาะจงปรากฏบน หน้าจอ ซึ่งบ่งบอกว่าหน้าจอมีข้อมูลครบถ้วนแล้ว

กลุ่มเทรด Jit ที่ไฮไลต์สไลซ์ "Jit compiling void"
รูปที่ 8 หากเห็นกิจกรรม JIT จำนวนมาก ให้ขยาย โปรไฟล์พื้นฐานจนถึงจุดที่แอปพร้อมใช้งาน

ผลลัพธ์

ทีม Gmail สำหรับ Wear OS จึงได้ทำการปรับปรุงต่อไปนี้จากการวิเคราะห์นี้

  • เนื่องจากสังเกตเห็นการแย่งชิงทรัพยากรระหว่างการเริ่มต้นแอปเมื่อดูกิจกรรมของ CPU จึงได้แทนที่ภาพเคลื่อนไหวของวงกลมหมุนที่ใช้เพื่อ ระบุว่าแอปกำลังโหลดด้วยรูปภาพแบบคงที่เพียงรูปเดียว นอกจากนี้ ยัง ยืดเวลาหน้าจอเริ่มต้นเพื่อเลื่อนสถานะการสั่นไหว ซึ่งเป็นสถานะหน้าจอที่ 2 ที่ใช้เพื่อระบุว่าแอปกำลังโหลด เพื่อเพิ่มทรัพยากร CPU ซึ่งช่วยปรับปรุงเวลาในการตอบสนองของการเริ่มต้นแอปได้ 50%
  • จากการดูเวลาที่ใช้ในOpenDexFilesFromOat* และกิจกรรม JIT ทำให้ทีมได้เปิดใช้การเขียนซ้ำ R8 ของโปรไฟล์พื้นฐาน ซึ่งช่วย ลดเวลาในการตอบสนองเริ่มต้นของแอปได้ 20%

ต่อไปนี้คือเคล็ดลับบางส่วนจากทีมเกี่ยวกับวิธีวิเคราะห์ประสิทธิภาพของแอปอย่างมีประสิทธิภาพ

  • ตั้งค่ากระบวนการต่อเนื่องที่สามารถรวบรวมการติดตามและ ผลลัพธ์ได้โดยอัตโนมัติ ลองตั้งค่าการติดตามอัตโนมัติสำหรับแอปโดยใช้การเปรียบเทียบ
  • ใช้การทดสอบ A/B สำหรับการเปลี่ยนแปลงที่คุณคิดว่าจะช่วยปรับปรุงสิ่งต่างๆ และปฏิเสธการเปลี่ยนแปลงเหล่านั้นหากไม่เป็นไปตามที่คาดไว้ คุณสามารถวัดประสิทธิภาพในสถานการณ์ต่างๆ ได้โดยใช้ไลบรารี Macrobenchmark

ดูข้อมูลเพิ่มเติมได้ที่แหล่งข้อมูลต่อไปนี้