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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

คุณสามารถ ส่งออกและนำเข้าไฟล์ฮีปดัมป์ จากแท็บการบันทึกที่ผ่านมาในโปรไฟล์ได้ 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

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