ภาพรวมการวัดประสิทธิภาพแอป

เอกสารนี้จะช่วยคุณระบุและแก้ไขปัญหาด้านประสิทธิภาพที่สำคัญในแอป

ปัญหาด้านประสิทธิภาพที่สำคัญ

มีหลายปัญหาที่อาจทำให้ประสิทธิภาพในแอปไม่ดี แต่ปัญหาที่พบบ่อยซึ่งควรตรวจสอบมีดังนี้

เวลาในการตอบสนองของการเริ่มต้น

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

มุ่งเน้นเป้าหมายการเริ่มต้นใช้งานต่อไปนี้ในแอป

  • Cold Start ในเวลาน้อยกว่า 500 มิลลิวินาที Cold Start จะเกิดขึ้นเมื่อแอปที่กำลังเปิดตัวไม่ได้อยู่ในหน่วยความจำของระบบ เหตุการณ์นี้จะเกิดขึ้นเมื่อเป็นครั้งแรกที่แอปเปิดขึ้นนับตั้งแต่รีบูตหรือนับตั้งแต่ที่ผู้ใช้หรือระบบหยุดกระบวนการของแอป Cold Start ต้องใช้การทำงานจากระบบมากที่สุด เนื่องจากต้องโหลดทุกอย่างจากพื้นที่เก็บข้อมูลและเริ่มต้นแอป พยายามทำให้ Cold Start ใช้เวลา 500 มิลลิวินาทีหรือน้อยกว่า
  • Warm Start ในเวลาน้อยกว่า 200 มิลลิวินาที และ Hot Start ในเวลาน้อยกว่า 150 มิลลิวินาที การเริ่มต้นแบบอุ่น เกิดขึ้นเมื่อกระบวนการของแอปพลิเคชันทำงานอยู่เบื้องหลัง แล้ว แต่ระบบต้องเริ่มต้น UI ใหม่หรือนำ กิจกรรมกลับมาที่เบื้องหน้า เช่น เมื่อผู้ใช้ออกจากแอปและ เปิดแอปอีกครั้งในเวลาต่อมา Hot Startจะเร็วกว่าเนื่องจากระบบแคชกิจกรรมของแอปไว้ในหน่วยความจำแล้ว และเพียงแค่นำมาไว้ที่เบื้องหน้าโดยไม่ต้องสร้างลำดับชั้นการแสดงผลใหม่ พยายามรักษา การเริ่มต้นแบบวอร์มให้ต่ำกว่า 200 มิลลิวินาที และการเริ่มต้นแบบฮอตให้ต่ำกว่า 150 มิลลิวินาที
  • เวลาในการตอบสนอง P95 และ P99 ใกล้เคียงกับเวลาในการตอบสนองตามค่ามัธยฐานมาก P95 และ P99 แสดงถึงเปอร์เซ็นไทล์ที่ 95 และ 99 ของเวลาเริ่มต้น ส่วนค่ามัธยฐาน คือเปอร์เซ็นไทล์ที่ 50 เมื่อแอปใช้เวลานานในการเริ่มต้น ผู้ใช้จะได้รับ ประสบการณ์ที่ไม่ดี การสื่อสารระหว่างกระบวนการ (IPC) และ I/O ที่ไม่จำเป็น ในระหว่างเส้นทางวิกฤตของการเริ่มต้นแอปอาจทำให้เกิดการแย่งชิงล็อกและ ทำให้เกิดความไม่สอดคล้องกัน
การเลื่อนกระตุก

Jank เป็นคำที่อธิบายอาการภาพกระตุกที่เกิดขึ้นเมื่อระบบสร้างและแสดงเฟรมไม่ทันเวลาเพื่อวาดลงบนหน้าจอตามอัตราการรีเฟรชที่ขอ 60 Hz ขึ้นไป อาการกระตุกจะเห็นได้ชัดที่สุดเมื่อเลื่อนหน้าจอ ซึ่งแทนที่จะเป็นการไหลที่ราบรื่นและเคลื่อนไหวได้ แต่กลับ มีการสะดุด อาการกระตุกจะเกิดขึ้นเมื่อการเคลื่อนไหวหยุดชั่วคราวระหว่างทางเป็นเวลา 1 เฟรมขึ้นไป เนื่องจากแอปใช้เวลานานกว่าในการแสดงเนื้อหาเมื่อเทียบกับระยะเวลาของเฟรมในระบบ

กำหนดเป้าหมายอัตราการรีเฟรช 90Hz ในแอป อัตราการแสดงผลทั่วไปคือ 60Hz แต่ในอุปกรณ์รุ่นใหม่ๆ จำนวนมากจะทำงานในโหมด 90Hz ระหว่างการโต้ตอบของผู้ใช้ เช่น การเลื่อน อุปกรณ์บางรุ่นรองรับอัตราที่สูงกว่านี้ถึง 120Hz

หากต้องการดูว่าอุปกรณ์ใช้อัตราการรีเฟรชใดในขณะนั้น ให้เปิดใช้การวางซ้อนโดยใช้ตัวเลือกสำหรับนักพัฒนาแอป > แสดงอัตราการรีเฟรชในส่วนการแก้ไขข้อบกพร่อง

ทรานซิชันไม่ราบรื่น

ซึ่งจะเห็นได้ชัดเจนในระหว่างการโต้ตอบ เช่น การสลับระหว่างแท็บหรือการโหลดกิจกรรมใหม่ การเปลี่ยนฉากประเภทนี้ ต้องเป็นภาพเคลื่อนไหวที่ราบรื่นและไม่มีความล่าช้าหรือภาพกะพริบ

ประสิทธิภาพการใช้พลังงานต่ำ

การทำงานจะลดการชาร์จแบตเตอรี่และท้ายที่สุดก็ลด อายุการใช้งานแบตเตอรี่

การจัดสรรหน่วยความจำซึ่งมาจากการสร้างออบเจ็กต์ใหม่ในโค้ดทำให้เกิดการทำงาน ในระบบ การจัดสรรเองไม่เพียงต้องใช้ความพยายามจาก Android Runtime (ART) เท่านั้น แต่การปล่อยออบเจ็กต์เหล่านี้ในภายหลัง (การเก็บขยะ) ก็ต้องใช้เวลาและความพยายามด้วย

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

อย่างไรก็ตาม การจัดสรรต้องใช้ความพยายาม ดังนั้นโปรดทราบว่าการจัดสรรออบเจ็กต์จำนวนมากในลูปด้านในอาจทำให้เกิดปัญหาด้านประสิทธิภาพ

ระบุปัญหา

หากต้องการแก้ไขปัญหาด้านประสิทธิภาพ ให้ระบุและตรวจสอบเส้นทางของผู้ใช้ที่สําคัญต่อไปนี้

  • โฟลว์การเริ่มต้นใช้งานทั่วไป รวมถึงจากตัวเรียกใช้และการแจ้งเตือน
  • หน้าจอที่ผู้ใช้เลื่อนดูข้อมูล
  • การเปลี่ยนระหว่างหน้าจอ
  • โฟลว์ที่ทำงานเป็นเวลานาน เช่น การนำทางหรือการเล่นเพลง

สําหรับโฟลว์แต่ละรายการ ให้ตรวจสอบสิ่งที่เกิดขึ้นโดยใช้เครื่องมือแก้ไขข้อบกพร่องต่อไปนี้

  • Perfetto: ช่วยให้คุณเห็นสิ่งที่เกิดขึ้นในอุปกรณ์ทั้งเครื่องด้วย ข้อมูลการจับเวลาที่แม่นยำ
  • เครื่องมือสร้างโปรไฟล์หน่วยความจำ: ช่วยให้คุณเห็นการจัดสรรหน่วยความจำที่เกิดขึ้นในฮีป
  • Simpleperf: แสดง Flame Graph ของการเรียกฟังก์ชันที่ใช้ CPU มากที่สุดในช่วงระยะเวลาหนึ่ง เมื่อคุณพบว่ามีบางอย่างใน Systrace ที่ใช้เวลานาน แต่ไม่ทราบสาเหตุ Simpleperf จะให้ข้อมูลเพิ่มเติมได้

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

  • โฟลว์การเริ่มต้นใช้งาน
  • Jank
    • เมตริกภาคสนาม
      • Vitals ของเฟรมใน Play Console: คุณไม่สามารถจำกัดเมตริกให้แคบลงเพื่อเจาะจงเส้นทางของผู้ใช้ที่เฉพาะเจาะจงภายใน Play Console ได้ โดยจะรายงานเฉพาะ Jank โดยรวม ทั่วทั้งแอป
      • การวัดที่กำหนดเองด้วย FrameMetricsAggregator: คุณใช้ FrameMetricsAggregator เพื่อบันทึกเมตริก Jank ระหว่างเวิร์กโฟลว์ ที่เฉพาะเจาะจงได้
    • การตรวจในห้องทดลอง
      • การเลื่อนด้วย Macrobenchmark
      • Macrobenchmark จะรวบรวมเวลาเฟรมโดยใช้dumpsys gfxinfo คำสั่งที่ครอบคลุมเส้นทางของผู้ใช้เดียว ซึ่งเป็นวิธี ทำความเข้าใจความผันผวนของ Jank ในเส้นทางของผู้ใช้ที่เฉพาะเจาะจง RenderTimeเมตริกที่ไฮไลต์ระยะเวลาที่เฟรมใช้ในการ วาดมีความสำคัญมากกว่าจำนวนเฟรมที่กระตุกสําหรับ การระบุการถดถอยหรือการปรับปรุง

App Link คือ Deep Link ตาม URL ของเว็บไซต์ที่ได้รับการยืนยันแล้วว่าเป็นของเว็บไซต์ของคุณ การยืนยัน App Link อาจไม่สำเร็จด้วยสาเหตุต่อไปนี้

  • ขอบเขตตัวกรอง Intent ไม่ถูกต้อง: เพิ่ม autoVerify ลงในตัวกรอง Intent สำหรับ URL ที่แอปตอบสนองได้เท่านั้น
  • การเปลี่ยนโปรโตคอลที่ไม่ได้รับการยืนยัน: การเปลี่ยนเส้นทางฝั่งเซิร์ฟเวอร์และโดเมนย่อยที่ไม่ได้รับการยืนยันถือเป็นความเสี่ยงด้านความปลอดภัยและจะยืนยันไม่สำเร็จ ซึ่งทำให้ลิงก์ autoVerify ทั้งหมดใช้งานไม่ได้ เช่น การเปลี่ยนเส้นทางลิงก์จาก HTTP ไปยัง HTTPS เช่น example.com ไปยัง www.example.com โดยไม่ยืนยันลิงก์ HTTPS อาจทำให้การยืนยันล้มเหลว โปรดยืนยัน App Link โดยการ เพิ่มตัวกรอง Intent
  • ลิงก์ที่ยืนยันไม่ได้: การเพิ่มลิงก์ที่ยืนยันไม่ได้เพื่อวัตถุประสงค์ในการทดสอบ อาจทำให้ระบบไม่ยืนยัน App Link สำหรับแอปของคุณ
  • เซิร์ฟเวอร์ที่ไม่น่าเชื่อถือ: ตรวจสอบว่าเซิร์ฟเวอร์เชื่อมต่อกับแอปไคลเอ็นต์ได้

ตั้งค่าแอปเพื่อการวิเคราะห์ประสิทธิภาพ

การตั้งค่าอย่างเหมาะสมเป็นสิ่งสำคัญเพื่อให้ได้เกณฑ์เปรียบเทียบที่แม่นยำ ทำซ้ำได้ และนำไปใช้ได้จริง จากแอป ทดสอบในระบบที่ใกล้เคียงกับเวอร์ชันที่ใช้งานจริงมากที่สุด ในขณะที่ระงับแหล่งที่มาของสัญญาณรบกวน ส่วนต่อไปนี้แสดงขั้นตอนเฉพาะสำหรับ APK และระบบที่คุณทำได้เพื่อเตรียมการตั้งค่าการทดสอบ ซึ่งบางขั้นตอนจะเฉพาะเจาะจงสำหรับกรณีการใช้งาน

Tracepoint

แอปสามารถวัดโค้ดด้วยเหตุการณ์การติดตามที่กำหนดเอง

ในขณะที่บันทึกการติดตาม การติดตามจะทำให้เกิดค่าใช้จ่ายเพิ่มเติมเล็กน้อยประมาณ 5μs ต่อส่วน ดังนั้นจึงไม่ควรใส่การติดตามไว้ในทุกๆ เมธอด การติดตามงานขนาดใหญ่กว่า 0.1 มิลลิวินาทีจะช่วยให้ได้ข้อมูลเชิงลึกที่สำคัญเกี่ยวกับคอขวด

ข้อควรพิจารณาเกี่ยวกับ APK

ตัวแปรการแก้ไขข้อบกพร่องมีประโยชน์ในการแก้ปัญหาและสัญลักษณ์ตัวอย่างสแต็ก แต่ส่งผลกระทบอย่างรุนแรงต่อประสิทธิภาพ อุปกรณ์ที่ใช้ Android 10 (API ระดับ 29) ขึ้นไปสามารถใช้ profileable android:shell="true" ใน ไฟล์ Manifest เพื่อเปิดใช้การสร้างโปรไฟล์ในบิลด์ที่เผยแพร่

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

การรวบรวม

คอมไพล์แอปในอุปกรณ์ให้อยู่ในสถานะที่ทราบ โดยทั่วไปคือ speed เพื่อความ เรียบง่าย หรือ speed-profile เพื่อให้ตรงกับประสิทธิภาพในเวอร์ชันที่ใช้งานจริงมากขึ้น (แม้ว่าการดำเนินการนี้จะต้องมีการวอร์มอัปแอปพลิเคชันและทิ้งโปรไฟล์ หรือ คอมไพล์โปรไฟล์พื้นฐานของแอป)

ทั้ง speed และ speed-profile จะลดปริมาณโค้ดที่ทำงานซึ่งตีความจาก DEX และส่งผลให้ปริมาณการคอมไพล์แบบ Just-In-Time (JIT) ในเบื้องหลังลดลง ซึ่งอาจทำให้เกิดการรบกวนอย่างมาก เฉพาะ speed-profile เท่านั้นที่ลดผลกระทบของการโหลดคลาสรันไทม์จาก Dex

คำสั่งต่อไปนี้จะคอมไพล์แอปพลิเคชันโดยใช้โหมด speed

adb shell cmd package compile -m speed -f com.example.packagename

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

/data/misc/profiles/ref/[package-name]/primary.prof

ข้อควรพิจารณาเกี่ยวกับระบบ

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

ในอุปกรณ์ที่รูทแล้ว ให้ลองใช้สคริปต์ lockClocks สำหรับ Microbenchmarks สคริปต์เหล่านี้จะทำสิ่งต่างๆ ต่อไปนี้

  • วาง CPU ที่ความถี่คงที่
  • ปิดใช้คอร์ขนาดเล็กและกำหนดค่า GPU
  • ปิดใช้การควบคุมอุณหภูมิ

เราไม่แนะนำให้ใช้lockClocksสคริปต์สำหรับการทดสอบที่เน้นประสบการณ์ของผู้ใช้ เช่น การทดสอบการเปิดแอป การทดสอบ DoU และการทดสอบ Jank แต่สคริปต์นี้อาจจำเป็นสำหรับ การลดสัญญาณรบกวนในการทดสอบ Microbenchmark

หากเป็นไปได้ ให้พิจารณาใช้เฟรมเวิร์กการทดสอบ เช่น Macrobenchmark ซึ่งจะช่วยลดสัญญาณรบกวนในการวัดผลและป้องกันความไม่ถูกต้องของการวัดผล

การเริ่มต้นแอปช้า: กิจกรรมแทรมโพลีนที่ไม่จำเป็น

กิจกรรม Trampoline อาจขยายเวลาเริ่มต้นของแอปโดยไม่จำเป็น และคุณควรทราบว่าแอปของคุณทำเช่นนี้หรือไม่ ดังที่แสดงในตัวอย่างต่อไปนี้ การติดตาม activityStart จะตามด้วย activityStart อีกรายการทันที โดยที่กิจกรรมแรกไม่ได้วาดเฟรมใดๆ

alt_text รูปที่ 1 ร่องรอยที่แสดงกิจกรรมแทรมโพลีน

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

การจัดสรรที่ไม่จำเป็นซึ่งทำให้เกิด GC บ่อยครั้ง

คุณอาจเห็นการเก็บขยะ (GC) เกิดขึ้นบ่อยกว่าที่คาดไว้ใน Systrace

ในตัวอย่างต่อไปนี้ ระบบจัดการหน่วยความจำที่ไม่ใช้แล้วทุกๆ 10 วินาทีระหว่างการดำเนินการที่ใช้เวลานานเป็นตัวบ่งชี้ว่าแอปอาจจัดสรรโดยไม่จำเป็นแต่สม่ำเสมอเมื่อเวลาผ่านไป

alt_text รูปที่ 2 การติดตามที่แสดงช่องว่างระหว่างเหตุการณ์ GC

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

เฟรมที่กระตุก

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

เมื่อมีการวาดเฟรมโดยที่แอปไม่ต้องทำงานมาก Choreographer.doFrame() จุดติดตามจะเกิดขึ้นทุกๆ 16.7 มิลลิวินาทีในอุปกรณ์ 60 FPS

alt_text รูปที่ 3 การติดตามที่แสดงเฟรมเร็วที่เกิดขึ้นบ่อย

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

alt_text รูปที่ 4 การติดตามที่แสดงเฟรมเร็วบ่อยๆ พร้อมการทำงานเป็นช่วงๆ

เมื่อเห็นว่าจังหวะปกติเกิดการหยุดชะงัก แสดงว่าเฟรมไม่เสถียร ดังที่แสดง ในรูปที่ 5 และ 6

alt_text รูปที่ 5 การติดตามที่แสดงเฟรมที่กระตุก

alt_text รูปที่ 6 การติดตามที่แสดงเฟรมที่กระตุกมากขึ้น

ในบางกรณี คุณต้องซูมเข้าที่จุดติดตามเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับ คอมโพเนนต์ UI ที่ Compose อัปเดต หรือดูว่า LazyColumn กำลังทำอะไรอยู่ ดังที่แสดงในรูปที่ 6 เมื่อวินิจฉัยคอขวดของ UI เหล่านี้ การติดตามระบบมาตรฐานอาจไม่แสดง Composable ที่เป็นสาเหตุที่แท้จริง ในกรณีเหล่านี้ ให้ใช้การติดตามการคอมโพสของ Jetpack Compose ซึ่งจะแสดงฟังก์ชันที่คอมโพสได้ที่แน่นอน โดยตรงภายในร่องรอย ทำให้ระบุการคอมโพสใหม่ที่ไม่คาดคิดได้ง่ายขึ้น รูปที่ 5 และ 6 แสดงผลลัพธ์ของการติดตามการคอมโพสิต

ดูข้อมูลเพิ่มเติมเกี่ยวกับการเพิ่มประสิทธิภาพ Compose ได้ที่ประสิทธิภาพของ Jetpack Compose ดูข้อมูลเพิ่มเติมเกี่ยวกับการระบุเฟรมที่กระตุกและ การแก้ไขข้อบกพร่องของสาเหตุได้ที่การแสดงผลช้า

ข้อผิดพลาดที่พบบ่อยเกี่ยวกับเลย์เอาต์แบบเลื่อน

การลบล้างสถานะการสนับสนุนทั้งหมดของเลย์เอาต์แบบ Lazy โดยไม่จำเป็นอาจ ทำให้เกิดการประกอบใหม่มากเกินไป เวลาในการแสดงผลเฟรมที่นาน และการกระตุก หากต้องการลดจำนวนรายการในลิสต์ที่ต้องอัปเดต ให้ใช้คีย์รายการสำหรับ รายการของคุณ และเปลี่ยนเฉพาะองค์ประกอบสถานะที่เฉพาะเจาะจงที่เปลี่ยนแปลง

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

การติดตั้งรายการเลื่อนที่ซ้อนกันอย่างไม่เหมาะสมอาจทำให้ประสิทธิภาพลดลง หลีกเลี่ยงการซ้อนเลย์เอาต์แบบเลื่อนที่โหลดแบบ Lazy ภายในคอนเทนเนอร์การเลื่อนอื่นโดยไม่มี ข้อจำกัดที่ชัดเจน ดูข้อมูลเพิ่มเติมได้ที่หลีกเลี่ยงการซ้อนคอมโพเนนต์ที่เลื่อนได้ในทิศทางเดียวกัน

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

แก้ไขข้อบกพร่องของแอป

ต่อไปนี้คือวิธีการแก้ไขข้อบกพร่องของประสิทธิภาพแอป

แก้ไขข้อบกพร่องของการเริ่มต้นแอปด้วย Systrace

ดูภาพรวมของกระบวนการเริ่มต้นแอปได้ที่เวลาเริ่มต้นแอป และดูภาพรวมของการติดตามระบบและการใช้ Android Studio Profiler ได้ในวิดีโอต่อไปนี้

คุณสามารถแยกประเภทสตาร์ทอัปได้ในขั้นตอนต่อไปนี้

  • Cold Startup: เริ่มต้นด้วยการสร้างกระบวนการใหม่ที่ไม่มีสถานะที่บันทึกไว้
  • Warm Startup: สร้างกิจกรรมใหม่ขณะใช้กระบวนการซ้ำ หรือ สร้างกระบวนการใหม่ด้วยสถานะที่บันทึกไว้
  • Hot Startup: รีสตาร์ทกิจกรรมและเริ่มที่การเพิ่มค่า

เราขอแนะนำให้บันทึก Systrace ด้วยแอปการติดตามระบบในอุปกรณ์ สำหรับ Android 10 ขึ้นไป ให้ใช้ Perfetto สำหรับ Android 9 และต่ำกว่า ให้ใช้ Systrace นอกจากนี้ เราขอแนะนำให้ดูไฟล์การติดตามด้วยโปรแกรมดูการติดตาม Perfetto บนเว็บ ดูข้อมูลเพิ่มเติมได้ที่ภาพรวมของการติดตามระบบ

โดยอิงตามสิ่งที่ควรพิจารณาดังนี้

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

  • GC พร้อมกัน: ปัญหานี้พบได้ทั่วไปและมีผลกระทบค่อนข้างน้อย แต่หากพบปัญหานี้บ่อยครั้ง ให้ลองตรวจสอบด้วยโปรไฟล์เลอร์หน่วยความจำของ Android Studio

  • I/O: ตรวจสอบ I/O ที่ดำเนินการระหว่างการเริ่มต้นระบบ และมองหาการหยุดทำงานเป็นเวลานาน

  • กิจกรรมสำคัญในเธรดอื่นๆ: กิจกรรมเหล่านี้อาจรบกวนเธรด UI ดังนั้นโปรดระวังงานในเบื้องหลังระหว่างการเริ่มต้น

เราขอแนะนำให้คุณเรียกใช้ reportFullyDrawn เมื่อการเริ่มต้นเสร็จสมบูรณ์จากมุมมองของแอปเพื่อปรับปรุงการรายงานเมตริกการเริ่มต้นแอป ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ reportFullyDrawn ได้ที่ส่วนเวลา ในการแสดงผลทั้งหมด คุณสามารถดึงเวลาเริ่มต้นที่กำหนดโดย RFD ผ่านตัวประมวลผลการติดตาม Perfetto และจะมีการปล่อยเหตุการณ์การติดตามที่ผู้ใช้มองเห็น

ใช้การติดตามระบบในอุปกรณ์

คุณสามารถใช้แอปที่ระดับระบบที่เรียกว่าการติดตามระบบเพื่อบันทึกการติดตามระบบในอุปกรณ์ แอปนี้ช่วยให้คุณบันทึกร่องรอยจากอุปกรณ์ได้โดยไม่ต้องเสียบปลั๊กหรือเชื่อมต่อกับ adb

ใช้เครื่องมือสร้างโปรไฟล์หน่วยความจำของ Android Studio

คุณใช้ Android Studio Memory Profiler เพื่อตรวจสอบแรงกดดันด้านหน่วยความจำ ที่อาจเกิดจากการรั่วไหลของหน่วยความจำหรือรูปแบบการใช้งานที่ไม่ดีได้ ซึ่งแสดงมุมมองแบบเรียลไทม์ของการจัดสรรออบเจ็กต์

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

หากต้องการสร้างโปรไฟล์หน่วยความจำของแอป ให้ทำตามขั้นตอนต่อไปนี้

  1. ตรวจหาปัญหาเกี่ยวกับหน่วยความจำ

    บันทึกเซสชันการสร้างโปรไฟล์หน่วยความจำของเส้นทางของผู้ใช้ที่คุณต้องการโฟกัส มองหาจำนวนออบเจ็กต์ที่เพิ่มขึ้น ดังที่แสดงในรูปที่ 7 ซึ่งในที่สุดจะ ทำให้เกิด GC ดังที่แสดงในรูปที่ 8

    alt_text รูปที่ 7 เพิ่มจำนวนออบเจ็กต์

    alt_text รูปที่ 8 การเก็บขยะ

    หลังจากระบุเส้นทางของผู้ใช้ที่เพิ่มแรงกดดันด้านหน่วยความจำแล้ว ให้วิเคราะห์สาเหตุหลักของแรงกดดันด้านหน่วยความจำ

  2. วินิจฉัยจุดที่เกิดปัญหาหน่วยความจำ

    เลือกช่วงในไทม์ไลน์เพื่อแสดงภาพทั้งการจัดสรรและ ขนาดแบบตื้น ดังที่แสดงในรูปที่ 9

    alt_text รูปที่ 9 ค่าสำหรับ Allocations และ Shallow Size

    คุณจัดเรียงข้อมูลนี้ได้หลายวิธี ต่อไปนี้คือตัวอย่าง วิธีที่แต่ละมุมมองช่วยวิเคราะห์ปัญหาได้

    • จัดเรียงตามคลาส: มีประโยชน์เมื่อคุณต้องการค้นหาคลาสที่ สร้างออบเจ็กต์ที่แคชหรือนำกลับมาใช้ใหม่จากพูลหน่วยความจำ

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

    • จัดเรียงตาม Callstack: มีประโยชน์เมื่อคุณต้องการค้นหาตำแหน่งที่มี Hotpath ซึ่งมีการจัดสรรหน่วยความจำ เช่น ภายในลูปหรือภายในฟังก์ชันที่เฉพาะเจาะจงซึ่งทำงานด้านการจัดสรรเป็นจำนวนมาก

    • ขนาดแบบตื้น: ติดตามเฉพาะหน่วยความจำของออบเจ็กต์เอง ซึ่งมีประโยชน์ ในการติดตามคลาสอย่างง่ายที่ประกอบด้วยค่าดั้งเดิมเป็นส่วนใหญ่

    • ขนาดที่เก็บไว้: แสดงหน่วยความจำทั้งหมดเนื่องจากออบเจ็กต์เองรวมถึงการอ้างอิงใดๆ ที่ออบเจ็กต์อ้างอิงเท่านั้น ซึ่งมีประโยชน์ในการติดตามแรงกดดันด้านหน่วยความจำเนื่องจากออบเจ็กต์ที่ซับซ้อน หากต้องการรับค่านี้ ให้ทำ การดัมพ์หน่วยความจำทั้งหมด ดังที่แสดงในรูปที่ 10 ระบบจะเพิ่มขนาดที่คงไว้เป็นคอลัมน์ ดังที่แสดงในรูปที่ 11

      alt_text รูปที่ 10 การทิ้งหน่วยความจำทั้งหมด

      คอลัมน์ขนาดที่คงไว้
      รูปที่ 11 คอลัมน์ขนาดที่คงไว้
  3. วัดผลกระทบของการเพิ่มประสิทธิภาพ

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

    หากต้องการวัดผลกระทบของการเพิ่มประสิทธิภาพ ให้วัด เวลาที่ใช้ระหว่าง GC ในไทม์ไลน์ของโปรไฟล์เลอร์ ผลกระทบเชิงบวกส่งผลให้ระยะเวลาระหว่าง GC นานขึ้น

    ผลกระทบขั้นสุดท้ายของการปรับปรุงหน่วยความจำมีดังนี้

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