บันทึกฮีพดัมพ์

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

หน้านี้อธิบายเครื่องมือที่ Android Studio มีไว้เพื่อรวบรวมและวิเคราะห์ฮีปดัมป์ หรือคุณจะตรวจสอบหน่วยความจำของแอปจาก บรรทัดคำสั่งด้วย dumpsys และยัง ดูเหตุการณ์ระบบจัดการหน่วยความจำที่ไม่ใช้แล้ว (GC) ใน Logcat ได้อีกด้วย

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

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

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

ดูข้อมูลเกี่ยวกับแนวทางปฏิบัติในการเขียนโปรแกรมที่ช่วยลดการใช้หน่วยความจำของแอปได้ที่ อ่านจัดการหน่วยความจำของแอป

ภาพรวมฮีปดัมป์

หากต้องการบันทึกฮีปดัมป์ ให้เลือกงาน วิเคราะห์การใช้หน่วยความจำ (ฮีปดัมป์) (ใช้ Profiler: run 'app' as debuggable (complete data)) เพื่อบันทึกฮีป ดัมป์ ขณะที่บันทึกฮีปดัมป์ ปริมาณหน่วยความจำ Java อาจเพิ่มขึ้นชั่วคราว ซึ่งเป็นเรื่องปกติเนื่องจากฮีปดัมป์เกิดขึ้นในกระบวนการเดียวกับแอปของคุณและต้องใช้หน่วยความจำบางส่วนเพื่อรวบรวมข้อมูล หลังจากบันทึกฮีปดัมป์แล้ว คุณจะเห็นข้อมูลต่อไปนี้

มุมมองฮีปดัมป์ใน Android Studio Profiler

รายการคลาสจะแสดงข้อมูลต่อไปนี้

  • การจัดสรร: จำนวนการจัดสรรในฮีป
  • ขนาดเนทีฟ: ปริมาณหน่วยความจำเนทีฟทั้งหมดที่ใช้โดยออบเจ็กต์ประเภทนี้ (หน่วยเป็น ไบต์) คุณจะเห็นหน่วยความจำที่นี่สำหรับออบเจ็กต์บางรายการที่จัดสรรใน Java เนื่องจาก Android ใช้หน่วยความจำเนทีฟสำหรับคลาสเฟรมเวิร์กบางรายการ เช่น Bitmap

  • ขนาดตื้น: ปริมาณหน่วยความจำ Java ทั้งหมดที่ใช้โดยออบเจ็กต์ประเภทนี้ (หน่วยเป็น ไบต์)

  • ขนาดที่เก็บไว้: ขนาดหน่วยความจำทั้งหมดที่เก็บไว้เนื่องจากอินสแตนซ์ทั้งหมดของ คลาสนี้ (หน่วยเป็นไบต์)

ใช้เมนูฮีปเพื่อกรองไปยังฮีปบางรายการ

  • ฮีปของแอป (ค่าเริ่มต้น): ฮีปหลักที่แอปของคุณจัดสรรหน่วยความจำ
  • ฮีปรูปภาพ: อิมเมจบูตของระบบ ซึ่งมีคลาสที่โหลดไว้ล่วงหน้าในระหว่างการบูต การจัดสรรที่นี่จะไม่ย้ายหรือหายไป
  • ฮีป Zygote: ฮีปคัดลอกเมื่อเขียนที่กระบวนการของแอปแยกออกมาใน ระบบ Android

ใช้เมนูแบบเลื่อนลงการจัดเรียงเพื่อเลือกวิธีจัดเรียงการจัดสรร

  • จัดเรียงตามคลาส (ค่าเริ่มต้น): จัดกลุ่มการจัดสรรทั้งหมดตามชื่อคลาส
  • จัดเรียงตามแพ็กเกจ: จัดกลุ่มการจัดสรรทั้งหมดตามชื่อแพ็กเกจ

ใช้เมนูแบบเลื่อนลงคลาสเพื่อกรองไปยังกลุ่มคลาส

  • คลาสทั้งหมด (ค่าเริ่มต้น): แสดงคลาสทั้งหมด รวมถึงคลาสจากไลบรารี และการขึ้นต่อกัน
  • แสดงหน่วยความจำรั่วไหลของกิจกรรม/Fragment: แสดงคลาสที่ทำให้เกิดหน่วยความจำรั่วไหล
  • แสดงคลาสโปรเจ็กต์: แสดงเฉพาะคลาสที่กำหนดโดยโปรเจ็กต์ของคุณ

คลิกชื่อคลาสเพื่อเปิดบานหน้าต่างอินสแตนซ์ อินสแตนซ์แต่ละรายการที่แสดงจะมีข้อมูลต่อไปนี้

  • ความลึก: จำนวนการข้ามที่สั้นที่สุดจากราก GC ไปยังอินสแตนซ์ที่เลือก
  • ขนาดเนทีฟ: ขนาดของอินสแตนซ์นี้ในหน่วยความจำเนทีฟ คอลัมน์นี้จะแสดงเฉพาะใน Android 7.0 ขึ้นไป
  • ขนาดตื้น: ขนาดของอินสแตนซ์นี้ในหน่วยความจำ Java
  • ขนาดที่เก็บไว้: ขนาดหน่วยความจำที่อินสแตนซ์นี้ครอบครอง (ตาม แผนผังผู้ครอบครอง)

คลิกอินสแตนซ์เพื่อแสดงรายละเอียดอินสแตนซ์ ซึ่งรวมถึงฟิลด์ และการอ้างอิง ประเภทฟิลด์และการอ้างอิงทั่วไปคือประเภทที่มีโครงสร้าง , อาร์เรย์ , และประเภทข้อมูลดั้งเดิม ใน Java คลิกขวาที่ฟิลด์หรือการอ้างอิงเพื่อไปยังอินสแตนซ์หรือบรรทัดที่เกี่ยวข้องในซอร์สโค้ด

  • ฟิลด์: แสดงฟิลด์ทั้งหมดในอินสแตนซ์นี้
  • การอ้างอิง: แสดงการอ้างอิงทั้งหมดไปยังออบเจ็กต์ที่ไฮไลต์ในแท็บ อินสแตนซ์
มุมมองอินสแตนซ์ ฟิลด์ และการอ้างอิง ในหน้าต่างเครื่องมือฮีปดัมป์

ตรวจหาบิตแมปที่ซ้ำกัน

นอกจากนี้ คุณยังตรวจหาบิตแมปที่ซ้ำซ้อนได้ในมุมมองฮีปดัมป์ตั้งแต่ Android Studio Narwhal 4 เป็นต้นไป

วิธีตรวจหาบิตแมปที่ซ้ำกันมีดังนี้

  1. เปิดแท็บ Profiler ใน Android Studio
  2. คลิกฮีปดัมป์ (หรือวิเคราะห์การใช้หน่วยความจำ) แล้วคลิกบันทึกเพื่อถ่ายภาพสถานะหน่วยความจำปัจจุบันของแอป
  3. สแกนผลการวิเคราะห์เพื่อหาเครื่องหมายสามเหลี่ยมคำเตือนสีเหลือง ⚠️ ซึ่ง Android Studio ใช้เพื่อแจ้งบิตแมปที่ซ้ำกันซึ่งจัดเก็บไว้หลายครั้ง
    • หรือไปที่ส่วนหัวของ Profiler เลือกกรองตาม: แล้วเลือกการตั้งค่าบิตแมปที่ซ้ำกัน
  4. คลิกรายการที่แจ้งเพื่อเปิดบานหน้าต่างการแสดงตัวอย่างบิตแมป ซึ่งช่วยให้คุณเห็นได้อย่างชัดเจนว่ารูปภาพใดที่ซ้ำกัน
  5. ใช้การยืนยันด้วยภาพเพื่อติดตามตรรกะการโหลดที่ซ้ำซ้อนในโค้ดและใช้กลยุทธ์การแคชที่ดีขึ้น
มองหาบิตแมปที่ซ้ำกันโดยใช้เครื่องหมายสามเหลี่ยมคำเตือนสีเหลือง ⚠️

ค้นหาหน่วยความจำรั่วไหล

หากต้องการกรองไปยังคลาสที่อาจเกี่ยวข้องกับหน่วยความจำรั่วไหลอย่างรวดเร็ว ให้เปิดเมนูแบบเลื่อนลงคลาสแล้วเลือกแสดงหน่วยความจำรั่วไหลของกิจกรรม/Fragment Android Studio จะแสดงคลาสที่ระบบคิดว่าบ่งชี้ถึงหน่วยความจำรั่วไหลสำหรับ Activity และ Fragment อินสแตนซ์ในแอป

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

  • การอ้างอิง Activity หรือ Context ที่มีอายุการใช้งานยาวนานซึ่งอาจทำให้กราฟการจัดองค์ประกอบ Compose ที่โฮสต์รั่วไหล (เช่น ComposeView และคอมโพสได้ย่อย)
  • ออบเจ็กต์สถานะ Jetpack Compose (MutableState) ตัวยึดสถานะ หรือแลมบ์ดาที่เก็บ Context ไว้รั่วไหล
  • ลืมล้างข้อมูล Listener หรือ Observer ในบล็อก onDispose ของ DisposableEffect
  • คลาสภายในที่ไม่ใช่แบบคงที่ เช่น Runnable ซึ่งสามารถเก็บอินสแตนซ์Activity ไว้ได้
  • แคชที่เก็บออบเจ็กต์ไว้นานกว่าที่จำเป็น

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

กระตุ้นให้เกิดหน่วยความจำรั่วไหลเพื่อทำการทดสอบ

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

นอกจากนี้ คุณยังกระตุ้นให้เกิดหน่วยความจำรั่วไหลได้ด้วยวิธีใดวิธีหนึ่งต่อไปนี้

  • หมุนอุปกรณ์จากแนวตั้งเป็นแนวนอนและกลับไปกลับมาหลายครั้งขณะอยู่ในสถานะกิจกรรมต่างๆ การหมุนอุปกรณ์มักทำให้แอป เกิดหน่วยความจำรั่วไหลของ Activity (และด้วยเหตุนี้จึงทำให้แผนผัง UI ของ Compose ที่โฮสต์และ แผนผังสถานะที่เกี่ยวข้องรั่วไหล) หากแอปของคุณมีการอ้างอิง Activity หรือ Context ภายในตัวยึดสถานะหรือการดำเนินการแบบอะซิงโครนัส
  • สลับไปมาระหว่างแอปของคุณกับแอปอื่นขณะอยู่ในสถานะกิจกรรมต่างๆ เช่น ไปที่หน้าจอหลัก แล้วกลับมาที่แอปของคุณ

ส่งออกและนำเข้าการบันทึกฮีปดัมป์

คุณสามารถ ส่งออกและนำเข้าไฟล์ฮีปดัมป์ จากแท็บการบันทึกที่ผ่านมาใน Profiler Android Studio จะบันทึกการบันทึกเป็นไฟล์ .hprof

หรือหากต้องการใช้เครื่องมือวิเคราะห์ไฟล์ .hprof อื่น เช่น jhat, คุณต้องแปลงไฟล์ .hprof จากรูปแบบ Android เป็นรูปแบบไฟล์ .hprof ของ Java SE หากต้องการแปลงรูปแบบไฟล์ ให้ใช้เครื่องมือ hprof-conv ที่มีให้ในไดเรกทอรี {android_sdk}/platform-tools/ เรียกใช้คำสั่ง hprof-conv พร้อมอาร์กิวเมนต์ 2 รายการ ได้แก่ ชื่อไฟล์ .hprof เดิมและตำแหน่งที่จะเขียนไฟล์ .hprof ที่แปลงแล้ว ซึ่งรวมถึงชื่อไฟล์ .hprof ใหม่ เช่น

hprof-conv heap-original.hprof heap-converted.hprof

แหล่งข้อมูลเพิ่มเติม