ทำความเข้าใจและแก้ปัญหาเกี่ยวกับหน่วยความจำของ Android

หน่วยความจำเป็นทรัพยากรที่สำคัญและมีอยู่อย่างจำกัดในอุปกรณ์ที่ทำงานด้วยระบบ Android ในฐานะนักพัฒนาแพลตฟอร์ม Android หรือ OEM การทำความเข้าใจวิธีการทำงานของหน่วยความจำในทุกระดับ ตั้งแต่รันไทม์ Java ไปจนถึงเคอร์เนล Linux เป็นสิ่งสำคัญในการสร้างระบบที่มีประสิทธิภาพและเสถียร

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

วัตถุประสงค์

หลังจากอ่านคู่มือนี้จนจบ คุณจะสามารถทำสิ่งต่อไปนี้ได้

  • อธิบายแนวคิดพื้นฐานของหน่วยความจำ Android รวมถึงโมเดลกระบวนการ Zygote และไฟล์ที่แมปหน่วยความจำ
  • แยกความแตกต่างระหว่าง Resident Set Size (RSS), Proportional Set Size (PSS) และ Unique Set Size (USS)
  • ใช้เครื่องมือบรรทัดคำสั่งมาตรฐาน เช่น dumpsys meminfo และ showmap เพื่อประเมินการใช้งานหน่วยความจำอย่างรวดเร็ว
  • บันทึกและวิเคราะห์ฮีปดัมป์ของ Java โดยใช้ AHAT เพื่อค้นหาการรั่วไหลและการจัดสรรที่มากเกินไป
  • ใช้ Perfetto และ heapprofd เพื่อทำโปรไฟล์ทั้งหน่วยความจำ Java และหน่วยความจำแบบเนทีฟในทั้งระบบ
  • ทำความเข้าใจตัวบ่งชี้การใช้หน่วยความจำทั่วทั้งระบบ เช่น Pressure Stall Information (PSI) และตรวจสอบกิจกรรม Low Memory Killer (LMK)
  • สังเกตกิจกรรมการเรียกคืนระดับเคอร์เนล ซึ่งรวมถึงการสลับ ZRAM และการขับไล่แคชหน้าเว็บ

โครงสร้างคำแนะนำ

คู่มือนี้แบ่งออกเป็นส่วนต่างๆ ต่อไปนี้ ซึ่งออกแบบมาให้อ่านตามลำดับ

  1. แนวคิดพื้นฐาน: หลักการทางเทคนิคหลักของหน่วยความจำ Android
  2. เครื่องมือประเมินผลแบบรวดเร็ว: การใช้ meminfo, showmap และ procstats เพื่อคัดแยกอย่างรวดเร็ว
  3. การวิเคราะห์หน่วยความจำ Java: ข้อมูลเจาะลึกฮีป Java ด้วย AHAT
  4. บิตแมปและหน่วยความจำ: ทำความเข้าใจว่ารูปภาพส่งผลต่อ RAM อย่างไรและใช้เครื่องมือเพื่อวิเคราะห์รูปภาพ
  5. การวิเคราะห์หน่วยความจำแบบเนทีฟ: การทำโปรไฟล์หน่วยความจำ C/C++ ด้วย Perfetto และ heapprofd
  6. WebView และหน่วยความจำ: ทำความเข้าใจสถาปัตยกรรมแบบหลายกระบวนการและหน่วยความจำที่ใช้ของ WebView
  7. โค้ดแอปคือหน่วยความจำ: ทำความเข้าใจว่าการโหลดคลาสและ Dex Bloat ส่งผลต่อ RAM อย่างไร
  8. ชุดข้อความและหน่วยความจำ: การวิเคราะห์ต้นทุนของสแต็กชุดข้อความแบบเนทีฟ
  9. ตำแหน่งหน่วยความจำและประสิทธิภาพ: ทำความเข้าใจว่ารูปแบบการเข้าถึงข้อมูลส่งผลต่อประสิทธิภาพของ CPU อย่างไร
  10. การผูกบริการและสถานะกระบวนการ: ทำความเข้าใจว่าทรัพยากร Dependency ข้ามกระบวนการส่งผลต่อคะแนน OOM อย่างไร
  11. การแก้ปัญหาทั้งระบบ: การตรวจสอบ PSI, LMK, การสลับ ZRAM และการขับไล่แคชของหน้าเว็บ
  12. การเรียกคืนหน่วยความจำ: การขับออกและการสลับ: ทำความเข้าใจ memcg, การเรียกเก็บเงิน และการเรียกคืนเชิงรุกด้วย memory.reclaim
  13. การโต้ตอบระหว่าง kswapd และ lmkd: ทำความเข้าใจวิธีการทำงานร่วมกันของ kswapd และ lmkd ภายใต้แรงกดดัน
  14. คืนหน้าหน่วยความจำไปยังระบบปฏิบัติการ: การใช้ madvise และ posix_fadvise เพื่อคืนหน้าฮีปและหน้าแคชไฟล์ที่ไม่ได้ใช้ไปยังเคอร์เนล
  15. คงการทำงานเบื้องหลังไว้ด้วยกระบวนการที่ใช้ทรัพยากรน้อย: การย้ายบริการที่ทำงานอยู่เบื้องหลังและเวิร์กเกอร์ไปยังกระบวนการเฉพาะ เพื่อไม่ให้ UI และหน่วยความจำกราฟิกมีลำดับความสำคัญสูงขึ้น

สิ่งที่ต้องดำเนินการก่อนและสภาพแวดล้อม

คู่มือนี้จะแสดงเวิร์กโฟลว์อ้างอิง ข้อมูลการเปรียบเทียบ และกรณีศึกษาที่สาธิตวิธีวิเคราะห์และแก้ไขปัญหาหน่วยความจำของ Android

  • เครื่องมือวิเคราะห์: เทคนิคในคู่มือนี้ใช้เครื่องมือประสิทธิภาพ Android มาตรฐานเป็นหลัก ซึ่งรวมถึง Perfetto, dumpsys meminfo, showmap และ AHAT
  • สิทธิ์ระดับรูท: เวิร์กโฟลว์การวินิจฉัยระดับระบบบางอย่าง (เช่น การตรวจสอบแรงดันหน่วยความจำเคอร์เนลหรือตัวนับ PMU ของฮาร์ดแวร์) ต้องใช้สิทธิ์ระดับรูทที่ยกระดับ (adb root) ในอุปกรณ์ userdebug หรือบิลด์โปรแกรมจำลอง

เริ่มต้นที่นี่: แนวคิดพื้นฐาน