การจัดสรรหน่วยความจำในกระบวนการต่างๆ

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

หน้านี้จะอธิบายพื้นฐานเกี่ยวกับวิธีที่ Android จัดสรรหน่วยความจำให้กับระบบและสำหรับแอปพลิเคชันของผู้ใช้ รวมถึงอธิบายวิธีที่ระบบปฏิบัติการตอบสนองต่อสถานการณ์ที่มีหน่วยความจำต่ำ

ประเภทของหน่วยความจำ

อุปกรณ์ Android มีหน่วยความจำ 3 ประเภท ได้แก่ RAM, zRAM และพื้นที่เก็บข้อมูล โปรดทราบว่าทั้ง CPU และ GPU เข้าถึง RAM เดียวกัน

ประเภทของหน่วยความจำ

รูปที่ 1 ประเภทหน่วยความจำ ได้แก่ RAM, zRAM และพื้นที่เก็บข้อมูล

  • RAM เป็นหน่วยความจำประเภทที่เร็วที่สุด แต่มักจะมีขีดจำกัดด้านขนาด อุปกรณ์ระดับสูงมักจะมี RAM มากที่สุด

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

  • พื้นที่เก็บข้อมูลมีข้อมูลที่ถาวรทั้งหมด เช่น ระบบไฟล์และโค้ดออบเจ็กต์ที่รวมไว้สำหรับแอป ไลบรารี และแพลตฟอร์มทั้งหมด พื้นที่เก็บข้อมูลมีความจุมากกว่าหน่วยความจำอีก 2 ประเภท ใน Android ระบบจะไม่ใช้พื้นที่เก็บข้อมูลสำหรับพื้นที่หน่วยความจำเสมือนเหมือนกับที่ใช้ในการใช้งาน Linux อื่นๆ เนื่องจากการเขียนบ่อยๆ อาจทำให้หน่วยความจำนี้เสื่อมสภาพและทำให้อายุการใช้งานของสื่อเก็บข้อมูลสั้นลง

หน้าหน่วยความจํา

RAM จะแบ่งออกเป็นหน้า โดยปกติแล้วแต่ละหน้าจะใช้หน่วยความจํา 4KB

ระบบจะถือว่าหน้าเว็บว่างหรือมีการใช้งาน หน้าว่างคือ RAM ที่ไม่ได้ใช้งาน หน้าที่ใช้งานอยู่คือ RAM ที่ระบบกำลังใช้งานอยู่ และจัดกลุ่มเป็นหมวดหมู่ต่อไปนี้

  • แคช: หน่วยความจำที่สำรองข้อมูลโดยไฟล์ในพื้นที่เก็บข้อมูล (เช่น โค้ดหรือไฟล์ที่แมปหน่วยความจำ) หน่วยความจำแคชมี 2 ประเภท ได้แก่
    • ส่วนตัว: เป็นเจ้าของโดยกระบวนการเดียวและไม่ได้แชร์
      • สะอาด: สำเนาไฟล์ในที่จัดเก็บข้อมูลที่ไม่มีการเปลี่ยนแปลง ซึ่งสามารถลบได้โดยใช้ kswapd เพื่อเพิ่มพื้นที่ว่างในหน่วยความจำ
      • ไม่เป็นระเบียบ: สำเนาไฟล์ที่แก้ไขแล้วในพื้นที่เก็บข้อมูล ซึ่งสามารถย้ายไปไว้ในหรือบีบอัดใน zRAM โดย kswapd เพื่อเพิ่มหน่วยความจำว่าง
    • แชร์: ใช้โดยหลายกระบวนการ
      • สะอาด: สำเนาไฟล์ในที่จัดเก็บข้อมูลที่ไม่มีการเปลี่ยนแปลง ซึ่งสามารถลบได้โดยใช้ kswapd เพื่อเพิ่มหน่วยความจำว่าง
      • มีการแก้ไข: สำเนาที่แก้ไขแล้วของไฟล์ในพื้นที่เก็บข้อมูล ซึ่งอนุญาตให้เขียนการเปลี่ยนแปลงกลับไปยังไฟล์ในพื้นที่เก็บข้อมูลเพื่อเพิ่มพื้นที่ว่างในหน่วยความจำได้โดยใช้ kswapd หรือใช้ msync() หรือ munmap() อย่างชัดเจน
  • ข้อมูลที่ไม่ระบุตัวตน: หน่วยความจำที่ไม่ได้สำรองข้อมูลโดยไฟล์ในที่จัดเก็บ (เช่น หน่วยความจำที่จัดสรรโดย mmap() ที่มีการตั้งค่า Flag MAP_ANONYMOUS)
    • สกปรก: สามารถย้าย/บีบอัดใน zRAM โดย kswapd เพื่อเพิ่มพื้นที่ว่างในหน่วยความจำ

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

การจัดการหน่วยความจําต่ำ

Android มีกลไกหลัก 2 อย่างสำหรับจัดการกับสถานการณ์หน่วยความจำต่ำ ได้แก่ เคอร์เนลไดมอนสลับและโปรแกรมที่ปิดแอปเมื่อมีหน่วยความจำต่ำ

ดีแอม่อนสำหรับสลับพื้นที่เก็บข้อมูลของเคิร์นเนล

เดมอนการแลกเปลี่ยนเคอร์เนล (kswapd) เป็นส่วนหนึ่งของเคอร์เนล Linux และแปลงหน่วยความจำที่ใช้ไปเป็นหน่วยความจำว่าง ซึ่งจะทำงานเมื่อหน่วยความจำว่างในอุปกรณ์เหลือน้อย เคอร์เนล Linux จะรักษาเกณฑ์หน่วยความจำว่างต่ำและสูง เมื่อหน่วยความจําว่างลดลงต่ำกว่าเกณฑ์ต่ำ kswapd จะเริ่มเรียกคืนหน่วยความจํา เมื่อหน่วยความจําว่างถึงเกณฑ์สูง kswapd จะหยุดเรียกคืนหน่วยความจํา

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

ลบหน้าเว็บที่ล้างแล้วซึ่งสำรองข้อมูลไว้ในพื้นที่เก็บข้อมูลแล้ว

รูปที่ 2 หน้าเว็บที่ล้างแล้วซึ่งสำรองข้อมูลไว้ในพื้นที่เก็บข้อมูลถูกลบ

kswapd สามารถย้ายหน้าเว็บแคชที่ไม่เป็นระเบียบแบบส่วนตัวและหน้าเว็บแคชที่ไม่เป็นระเบียบแบบไม่ระบุตัวตนไปยัง zRAM ซึ่งจะได้รับการบีบอัด ซึ่งจะช่วยเพิ่มหน่วยความจำที่พร้อมใช้งานใน RAM (หน้าว่าง) หากกระบวนการพยายามเข้าถึงหน้าที่ยังไม่ได้เขียนลงใน zRAM ระบบจะยกเลิกการบีบอัดหน้านั้นและย้ายกลับไปยัง RAM หากกระบวนการที่เชื่อมโยงกับหน้าเว็บที่บีบอัดถูกยกเลิก ระบบจะลบหน้าเว็บออกจาก zRAM

หากจำนวนหน่วยความจำว่างลดลงต่ำกว่าเกณฑ์ที่กำหนด ระบบจะเริ่มฆ่ากระบวนการ

ย้ายหน้าเว็บที่ยังไม่ได้บันทึกไปยัง zRAM และบีบอัด

รูปที่ 3 ย้ายหน้าเว็บที่ยังไม่ได้บันทึกไปยัง zRAM และบีบอัด

โปรแกรมที่กินหน่วยความจำมาก

หลายครั้ง kswapd ไม่สามารถเพิ่มหน่วยความจำให้กับระบบได้ ในกรณีนี้ ระบบจะใช้ onTrimMemory() เพื่อแจ้งให้แอปทราบว่าหน่วยความจําเหลือน้อยและควรลดการจัดสรร หากยังไม่เพียงพอ เคอร์เนลจะเริ่มฆ่ากระบวนการเพื่อเพิ่มพื้นที่ว่างในหน่วยความจำ โดยจะใช้ Low-memory killer (LMK) ในการดำเนินการนี้

LMK ใช้คะแนน "หน่วยความจำไม่เพียงพอ" ที่ชื่อ oom_adj_score เพื่อจัดลําดับความสําคัญของกระบวนการที่ทํางานอยู่เพื่อตัดสินใจว่าจะฆ่ากระบวนการใด ระบบจะหยุดกระบวนการที่มีคะแนนสูงก่อน แอปที่ทำงานอยู่เบื้องหลังจะถูกหยุดก่อน และกระบวนการของระบบจะถูกหยุดเป็นลำดับสุดท้าย ตารางต่อไปนี้แสดงหมวดหมู่การให้คะแนน LMK จากสูงไปต่ำ ระบบจะลบรายการในหมวดหมู่ที่มีคะแนนสูงสุดในแถวที่ 1 ออกก่อน

กระบวนการ Android, คะแนนสูงสุดที่ด้านบน

รูปที่ 4 กระบวนการของ Android โดยกระบวนการที่มีคะแนนสูงจะแสดงที่ด้านบนและกระบวนการที่มีคะแนนต่ำจะแสดงที่ด้านล่าง

คำอธิบายสำหรับหมวดหมู่ต่างๆ ในตารางด้านบนมีดังนี้

  • แอปที่ทำงานอยู่เบื้องหลัง: แอปที่ทำงานก่อนหน้านี้และไม่ได้ใช้งานอยู่ในขณะนี้ LMK จะปิดแอปเบื้องหลังก่อน โดยเริ่มจากแอปที่มีoom_adj_scoreสูงสุด

  • แอปก่อนหน้า: แอปที่ทำงานอยู่เบื้องหลังซึ่งใช้งานล่าสุด แอปก่อนหน้าจะมีลําดับความสําคัญสูงกว่า (คะแนนต่ำกว่า) แอปที่ทำงานอยู่เบื้องหลัง เนื่องจากมีแนวโน้มว่าผู้ใช้จะเปลี่ยนไปใช้แอปก่อนหน้ามากกว่าแอปที่ทำงานอยู่เบื้องหลัง

  • แอป Home: แอปนี้เป็นแอปตัวเปิดแอป การปิดแอปนี้จะทำให้วอลเปเปอร์หายไป

  • บริการ: แอปพลิเคชันจะเริ่มต้นบริการและอาจรวมถึงการซิงค์หรืออัปโหลดไปยังระบบคลาวด์

  • แอปที่สังเกตได้: แอปที่ทำงานอยู่เบื้องหลังซึ่งผู้ใช้รับรู้ได้ เช่น การดำเนินการค้นหาที่แสดง UI ขนาดเล็กหรือการฟังเพลง

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

  • ถาวร (บริการ): บริการหลักสำหรับอุปกรณ์ เช่น โทรศัพท์และ Wi-Fi

  • ระบบ: กระบวนการของระบบ เมื่อกระบวนการเหล่านี้ถูกหยุด โทรศัพท์อาจดูเหมือนจะรีบูต

  • เนทีฟ: กระบวนการระดับต่ำมากที่ระบบใช้ (เช่น kswapd)

ผู้ผลิตอุปกรณ์สามารถเปลี่ยนลักษณะการทำงานของ LMK ได้

กำลังคำนวณหน่วยความจําที่ใช้

เคอร์เนลจะติดตามหน้าหน่วยความจำทั้งหมดในระบบ

หน้าที่กระบวนการต่างๆ ใช้

รูปที่ 5 หน้าที่กระบวนการต่างๆ ใช้

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

หน้าเว็บที่แอป 2 แอปแชร์

รูปที่ 6 หน้าเว็บที่แชร์โดย 2 แอป (ตรงกลาง)

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

  • Resident Set Size (RSS): จํานวนหน้าเว็บที่แชร์และไม่แชร์ที่แอปใช้
  • ขนาดชุดตามสัดส่วน (PSS): จำนวนหน้าที่ไม่ได้แชร์ซึ่งแอปใช้และการกระจายหน้าที่แชร์อย่างสม่ำเสมอ (เช่น หากมี 3 กระบวนการแชร์ 3 MB แต่ละกระบวนการจะได้รับ PSS 1 MB)
  • ขนาดชุดที่ไม่ซ้ำกัน (USS): จํานวนหน้าเว็บที่ไม่ได้แชร์ซึ่งแอปใช้ (ไม่รวมหน้าเว็บที่แชร์)

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

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