บิตแมปมักเป็นออบเจ็กต์ที่ใช้หน่วยความจำมากที่สุดในแอป การดำเนินการถอดรหัสและปรับขนาดมักอยู่ในเส้นทางวิกฤตสำหรับการแสดงผลเฟรม การเพิ่มประสิทธิภาพการใช้งานหน่วยความจำบิตแมปจะช่วยปรับปรุงการตอบสนองของ 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 มีการวิเคราะห์ฮีปอัตโนมัติ โดยจะระบุออบเจ็กต์ที่ควรได้รับการเก็บขยะแล้วแต่ยังคงอยู่ในหน่วยความจำ เช่น บิตแมปที่เก็บไว้โดยกิจกรรมหรือ Fragment ที่ถูกทำลาย
เอกสารประกอบเกี่ยวกับประสิทธิภาพของบิตแมป
แหล่งข้อมูลเหล่านี้ให้คำแนะนำที่ครอบคลุมเกี่ยวกับแนวทางปฏิบัติแนะนำสำหรับการจัดการบิตแมปอย่างมีประสิทธิภาพในคอมโพเนนต์ต่างๆ ของ Android
รายการตรวจสอบสำหรับนักพัฒนาแอปเพื่อเพิ่มประสิทธิภาพการใช้งานหน่วยความจำบิตแมป
หากต้องการเพิ่มประสิทธิภาพหน่วยความจำบิตแมป ให้ทำตามหลักการสำคัญ 3 ข้อ ได้แก่ ลด ใช้ซ้ำ และรีไซเคิล
- ลด: ลดหน่วยความจำที่ใช้เริ่มต้นเมื่อโหลดหรือแสดงบิตแมป
- ใช้ซ้ำ: ใช้กลไกการแคชเพื่อหลีกเลี่ยงการจัดสรรบิตแมป ที่ซ้ำซ้อน
- รีไซเคิล: ปล่อยทรัพยากรอย่างเชิงรุกเพื่อให้กระบวนการที่ทำงานอยู่สามารถจัดสรรหน่วยความจำใหม่ได้
รายการตรวจสอบสำหรับนักพัฒนาแอปต่อไปนี้จะช่วยคุณเพิ่มประสิทธิภาพการใช้งานหน่วยความจำบิตแมปได้
| หลักการสำคัญ | พื้นที่ | คำอธิบาย |
|---|---|---|
| ลด | กำจัดบิตแมปที่ซ้ำกัน | วิเคราะห์ฮีปดัมพ์ โดยใช้เครื่องมือสร้างโปรไฟล์หน่วยความจำ เพื่อตรวจหาการจัดสรรบิตแมปที่ซ้ำซ้อน โปรดดูคำแนะนำในการจัดการหน่วยความจำบิตแมป |
| ใช้ประโยชน์จากไลบรารีการโหลดรูปภาพ | ใช้ไลบรารี เช่น Glide และ Coil เพื่อทำให้การสร้างเธรด การแคช และการถอดรหัสที่มีประสิทธิภาพเป็นไปโดยอัตโนมัติ | |
| ใช้การลดขนาดความละเอียดของรูปภาพ | ถอดรหัสรูปภาพให้ตรงกับขนาดคอนเทนเนอร์ UI เป้าหมายแทนการโหลดชิ้นงานที่มีความละเอียดเต็ม | |
| ใช้ RGB_565 สำหรับรูปภาพทึบแสง | ลดหน่วยความจำที่ใช้ลง 50% โดยเปลี่ยนจาก ARGB_8888 เป็นการกำหนดค่า 16 บิตสำหรับรูปภาพที่ไม่มีความโปร่งใส |
|
| จัดลำดับความสำคัญของ VectorDrawable | ใช้ เวกเตอร์สำหรับไอคอนและกราฟิกพื้นฐาน เพื่อให้มั่นใจว่าการปรับขนาดจะคมชัดและใช้หน่วยความจำน้อยที่สุด | |
| เพิ่มประสิทธิภาพการแสดงรูปภาพฝั่งเซิร์ฟเวอร์ | กำหนดค่า API แบ็กเอนด์เพื่อ แสดงรูปภาพที่ปรับให้เหมาะกับความหนาแน่นของอุปกรณ์ และขนาด ImageView | |
| กำจัดระยะขอบโปร่งใส | หลีกเลี่ยงการจัดสรรหน่วยความจำสำหรับพิกเซล "ที่มองไม่เห็น" โดยใช้ InsetDrawable หรือระยะขอบเลย์เอาต์แทนระยะขอบที่ฝังไว้ ดูที่หัวข้อการสร้างแอป Android ที่มีประสิทธิภาพด้านหน่วยความจำ | |
| ใช้ซ้ำ | กำหนดค่าขนาดแคชที่เหมาะสม | ปรับแต่งขีดจำกัดแคชในหน่วยความจำและแคชดิสก์ตาม RAM ของอุปกรณ์และความละเอียดหน้าจอ โปรดดูหัวข้อ การแคชบิตแมป |
| รีไซเคิล | ล้างทรัพยากรในเบื้องหลัง | ใช้ TRIM_MEMORY_BACKGROUND เพื่อล้างแคชและปรับปรุงการทำงานของกระบวนการต่อไปได้ในระหว่างที่ระบบใช้หน่วยความจำมาก |
| ปล่อยชิ้นงานเมื่อ UI ซ่อนอยู่ | ใช้ TRIM_MEMORY_UI_HIDDEN เพื่อปล่อยแคชบิตแมปเมื่อผู้ใช้มองไม่เห็นแอปอีกต่อไป |
|
| ตรวจสอบหน่วยความจำรั่วไหล | ใช้ LeakCanary และ เครื่องมือสร้างโปรไฟล์หน่วยความจำ เพื่อค้นหาบิตแมปที่เก็บไว้หลังจากที่ LifecycleOwner ถูกทำลาย โปรดดูหัวข้อ จัดการหน่วยความจำของแอป |