บิตแมปมักเป็นออบเจ็กต์ที่ใช้หน่วยความจำมากที่สุดในแอป การดำเนินการถอดรหัสและปรับขนาดมักอยู่ในเส้นทางวิกฤตสำหรับการแสดงผลเฟรม การเพิ่มประสิทธิภาพการใช้งานหน่วยความจำบิตแมปช่วยปรับปรุงการตอบสนองของ UI, อายุการใช้งานแบตเตอรี่ และความเสถียรโดยรวมได้อย่างมาก โดยการลดการกระตุก, ANR และการหยุดทำงานของกระบวนการที่เกี่ยวข้องกับ OOM
ระบุการใช้งานหน่วยความจำบิตแมปสูง
Android Vitals มีเมตริกเกี่ยวกับหน่วยความจำที่ใช้บิตแมปของแอปโดยการรวบรวมข้อมูลจากอุปกรณ์ Android เมตริกเหล่านี้จะคำนวณเป็นสรุปข้อมูลรายวันในช่วง 28 วันโดยค่าเริ่มต้น ข้อมูลนี้ช่วยระบุแนวโน้มและการถดถอยที่อาจเกิดขึ้นในประสิทธิภาพของหน่วยความจำในอุปกรณ์และเวอร์ชันต่างๆ
Android Vitals จะแชร์การใช้งานหน่วยความจำบิตแมปของแอปที่แบ่งตาม สถานะกระบวนการต่อไปนี้ :
- เบื้องหน้า: กระบวนการของแอปมองเห็นได้ คาดว่า P99 จะสูงกว่าสถานะกระบวนการอื่นๆ อย่างมากเมื่อเทียบกับเบื้องหน้า แต่นักพัฒนาแอปควรตรวจสอบหากอัตราส่วน P99/P50 มีนัยสำคัญ (เช่น สูงกว่า 3.5 เท่า) เนื่องจากมักบ่งชี้ถึงหน่วยความจำบิตแมปรั่วไหล คุณสามารถระบุได้โดยดูความแตกต่างระหว่างการใช้งานทั่วไป (P50) กับการใช้งานที่ผิดปกติ (P99) ในขณะที่การขยายชิ้นงานทั่วไปจะเพิ่มหน่วยความจำอย่างสม่ำเสมอในทุกเปอร์เซ็นไทล์ แต่หน่วยความจำรั่วไหลจะเพิ่มขึ้นเมื่อเวลาผ่านไป ทำให้ข้อมูลส่วนท้าย (P99) เบ้ไปอย่างมาก ตรวจสอบว่าการจัดสรรบิตแมปเบื้องหน้าไม่ได้คงอยู่โดยไม่จำเป็นหลังจากที่แอปเปลี่ยนไปอยู่ในสถานะอื่นๆ
- บริการที่ผู้ใช้รับรู้: กระบวนการของแอปกำลังทำงานอยู่ในสถานะที่ รับรู้ได้ ซึ่งรวมถึงบริการที่ทำงานอยู่เบื้องหน้า งานที่เร่งด่วน และงานการโอนข้อมูลที่เริ่มต้นโดยผู้ใช้ แอปต้องไม่เก็บการจัดสรรบิตแมปเบื้องหน้าขนาดใหญ่ไว้เมื่อเปลี่ยนไปอยู่ในสถานะเหล่านี้ เนื่องจากบริการเหล่านี้ออกแบบมาสำหรับงานที่ใช้เวลานาน การเก็บชิ้นงานขนาดใหญ่ไว้จะทำให้ประสบการณ์ของผู้ใช้โดยรวมแย่ลงและบังคับให้ Low Memory Killer Daemon (LMKD) เรียกคืนหน่วยความจำโดยการยุติกระบวนการที่มีลำดับความสำคัญต่ำกว่า
- เบื้องหลัง: แอปกำลังเรียกใช้บริการที่ทำงานอยู่เบื้องหลัง หรือเพิ่งเปลี่ยนไปทำงานอยู่ เบื้องหลัง แต่ยังไม่ได้แคช เนื่องจากสถานะกระบวนการนี้มีความสำคัญน้อยกว่ากระบวนการเบื้องหน้าหรือกระบวนการที่รับรู้ได้ แอปจึงควรปล่อยชิ้นงานบิตแมปขนาดใหญ่อย่างชัดเจนในที่นี้เพื่อลดการใช้หน่วยความจำ
- แคช: แอปอยู่ในสถานะแคช สถานะนี้มีความไวสูงต่อการใช้หน่วยความจำของระบบ เช่น LMK แอปต้องลดการใช้งานหน่วยความจำบิตแมปในสถานะนี้อย่างเชิงรุกเพื่อหลีกเลี่ยงไม่ให้ระบบปฏิบัติการนำออก
ปัจจัยที่ทำให้การใช้งานหน่วยความจำบิตแมปสูง
ระบบอาจรวมหน่วยความจำเสมือนที่ไม่เคยใช้ในการคำนวณด้วย หากเห็นการใช้งานหน่วยความจำบิตแมปสูงอย่างไม่คาดคิด ให้ตรวจสอบว่าคุณไม่ได้จัดสรรหน่วยความจำที่ไม่ได้ใช้
แหล่งข้อมูล
วิเคราะห์บิตแมปใน Android Studio
การสร้างโปรไฟล์บิตแมปใน Android Studio
ใช้เครื่องมือสร้างโปรไฟล์หน่วยความจำเพื่อตรวจสอบการจัดสรรหน่วยความจำแบบเรียลไทม์ จับภาพฮีปดัมพ์ และวิเคราะห์ออบเจ็กต์เพื่อหาหน่วยความจำรั่วไหล นอกจากนี้ ให้ใช้ฮีปแอนาไลเซอร์เพื่อตรวจหาหน่วยความจำรั่วไหล ระบุการจัดสรรบิตแมปที่ซ้ำกัน และแสดงภาพการเก็บรักษาออบเจ็กต์
การตรวจหาหน่วยความจำรั่วไหลอัตโนมัติด้วย LeakCanary
ผสานรวมไลบรารี LeakCanary เพื่อทำให้การตรวจหาหน่วยความจำรั่วไหลในแอปเป็นไปโดยอัตโนมัติ LeakCanary มีการวิเคราะห์ฮีปอัตโนมัติ โดยจะระบุออบเจ็กต์ที่ควรได้รับการเก็บขยะแล้วแต่ยังคงอยู่ในหน่วยความจำ เช่น บิตแมปที่คอมโพเนนต์ที่ถูกทำลายเก็บไว้
เอกสารประกอบเกี่ยวกับประสิทธิภาพของบิตแมป
แหล่งข้อมูลเหล่านี้ให้คำแนะนำที่ครอบคลุมเกี่ยวกับแนวทางปฏิบัติแนะนำสำหรับการจัดการบิตแมปอย่างมีประสิทธิภาพในคอมโพเนนต์ Android ต่างๆ
รายการตรวจสอบสำหรับนักพัฒนาแอปเพื่อเพิ่มประสิทธิภาพการใช้งานหน่วยความจำบิตแมป
หากต้องการเพิ่มประสิทธิภาพหน่วยความจำบิตแมป ให้ทำตามหลักการสำคัญ 3 ข้อ ได้แก่ ลด ใช้ซ้ำ และรีไซเคิล
- ลด: ลดหน่วยความจำที่ใช้เริ่มต้นเมื่อโหลดหรือแสดงบิตแมป
- ใช้ซ้ำ: ใช้กลไกการแคชเพื่อหลีกเลี่ยงการจัดสรรบิตแมป ที่ซ้ำกัน
- รีไซเคิล: ปล่อยทรัพยากรอย่างเชิงรุกเพื่อให้กระบวนการที่ทำงานอยู่สามารถจัดสรรหน่วยความจำใหม่ได้
รายการตรวจสอบสำหรับนักพัฒนาแอปต่อไปนี้จะช่วยคุณเพิ่มประสิทธิภาพการใช้งานหน่วยความจำบิตแมปได้
| หลักการสำคัญ | พื้นที่ | คำอธิบาย |
|---|---|---|
| ลด | กำจัดบิตแมปที่ซ้ำกัน | วิเคราะห์ฮีปดัมพ์ โดยใช้เครื่องมือสร้างโปรไฟล์หน่วยความจำ เพื่อตรวจหาการจัดสรรบิตแมปที่ซ้ำกัน ดูคู่มือการจัดการหน่วยความจำบิตแมป |
| ใช้ประโยชน์จากไลบรารีการโหลดรูปภาพ | ใช้ไลบรารี เช่น Glide และ Coil เพื่อทำให้การสร้างเธรด การแคช และการถอดรหัสที่มีประสิทธิภาพเป็นไปโดยอัตโนมัติ | |
| ใช้การลดขนาดความละเอียดของรูปภาพ | ถอดรหัสรูปภาพให้ตรงกับขนาดคอนเทนเนอร์ UI เป้าหมายแทนที่จะโหลดชิ้นงานที่มีความละเอียดเต็ม | |
| ใช้ RGB_565 สำหรับรูปภาพทึบแสง | ลดหน่วยความจำที่ใช้ลง 50% โดย เปลี่ยนจาก ARGB_8888 เป็นการกำหนดค่า 16 บิต สำหรับรูปภาพที่ไม่มีความโปร่งใส |
|
| จัดลำดับความสำคัญของ VectorDrawable | ใช้ เวกเตอร์สำหรับไอคอนและกราฟิกพื้นฐาน เพื่อให้มั่นใจว่าการปรับขนาดจะคมชัดและใช้หน่วยความจำน้อยที่สุด | |
| เพิ่มประสิทธิภาพการแสดงรูปภาพฝั่งเซิร์ฟเวอร์ | กำหนดค่า API แบ็กเอนด์เพื่อ แสดงรูปภาพที่ปรับให้เหมาะกับความหนาแน่นของอุปกรณ์ และขนาดคอนเทนเนอร์ UI | |
| กำจัดระยะขอบโปร่งใส | หลีกเลี่ยงการจัดสรรหน่วยความจำสำหรับพิกเซล "ที่มองไม่เห็น" โดยใช้ InsetDrawable หรือระยะขอบเลย์เอาต์แทนระยะขอบที่ฝังไว้ ดูการสร้างแอป Android ที่มีประสิทธิภาพด้านหน่วยความจำ | |
| ใช้ซ้ำ | กำหนดค่าขนาดแคชที่เหมาะสม | ปรับขีดจำกัดแคชในหน่วยความจำและแคชดิสก์ตาม RAM ของอุปกรณ์และความละเอียดหน้าจอ ดูการแคชบิตแมป |
| รีไซเคิล | ล้างทรัพยากรในเบื้องหลัง | ใช้ TRIM_MEMORY_BACKGROUND เพื่อล้างแคชและปรับปรุงการอยู่รอดของกระบวนการระหว่างการใช้หน่วยความจำของระบบ |
| ปล่อยชิ้นงานเมื่อซ่อน UI | ใช้ TRIM_MEMORY_UI_HIDDEN เพื่อปล่อยแคชบิตแมปเมื่อผู้ใช้มองไม่เห็นแอปอีกต่อไป |
|
| ตรวจสอบหน่วยความจำรั่วไหล | ใช้ LeakCanary และ เครื่องมือสร้างโปรไฟล์หน่วยความจำ เพื่อค้นหาบิตแมปที่เก็บไว้หลังจากทำลาย LifecycleOwner แล้ว ดูจัดการหน่วยความจำของแอป |