แพลตฟอร์ม 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()
ที่มีการตั้งค่า FlagMAP_ANONYMOUS
)- สกปรก: สามารถย้าย/บีบอัดใน zRAM โดย
kswapd
เพื่อเพิ่มพื้นที่ว่างในหน่วยความจำ
- สกปรก: สามารถย้าย/บีบอัดใน zRAM โดย
อัตราส่วนของหน้าว่างและหน้าที่ใช้จะแตกต่างกันไปเมื่อเวลาผ่านไปเนื่องจากระบบจัดการ RAM อย่างสม่ำเสมอ แนวคิดที่นำเสนอในส่วนนี้เป็นกุญแจสำคัญในการจัดการสถานการณ์ที่มีหน่วยความจำต่ำ ส่วนถัดไปของเอกสารนี้จะอธิบายเรื่องนี้อย่างละเอียด
การจัดการหน่วยความจําต่ำ
Android มีกลไกหลัก 2 อย่างสำหรับจัดการกับสถานการณ์หน่วยความจำต่ำ ได้แก่ เคอร์เนลไดมอนสลับและโปรแกรมที่ปิดแอปเมื่อมีหน่วยความจำต่ำ
ดีแอม่อนสำหรับสลับพื้นที่เก็บข้อมูลของเคิร์นเนล
เดมอนการแลกเปลี่ยนเคอร์เนล (kswapd
) เป็นส่วนหนึ่งของเคอร์เนล Linux และแปลงหน่วยความจำที่ใช้ไปเป็นหน่วยความจำว่าง ซึ่งจะทำงานเมื่อหน่วยความจำว่างในอุปกรณ์เหลือน้อย เคอร์เนล Linux จะรักษาเกณฑ์หน่วยความจำว่างต่ำและสูง
เมื่อหน่วยความจําว่างลดลงต่ำกว่าเกณฑ์ต่ำ kswapd
จะเริ่มเรียกคืนหน่วยความจํา เมื่อหน่วยความจําว่างถึงเกณฑ์สูง kswapd
จะหยุดเรียกคืนหน่วยความจํา
kswapd
สามารถเรียกคืนหน้าเว็บที่สะอาดได้โดยลบหน้าเว็บดังกล่าว เนื่องจากหน้าเว็บเหล่านั้นได้รับการสำรองข้อมูลและไม่มีการแก้ไข หากกระบวนการพยายามเข้าถึงหน้าที่สะอาดซึ่งถูกลบไปแล้ว ระบบจะคัดลอกหน้านั้นจากพื้นที่เก็บข้อมูลไปยัง RAM การดำเนินการนี้เรียกว่าการแบ่งหน้าตามดีมานด์
รูปที่ 2 หน้าเว็บที่ล้างแล้วซึ่งสำรองข้อมูลไว้ในพื้นที่เก็บข้อมูลถูกลบ
kswapd
สามารถย้ายหน้าเว็บแคชที่ไม่เป็นระเบียบแบบส่วนตัวและหน้าเว็บแคชที่ไม่เป็นระเบียบแบบไม่ระบุตัวตนไปยัง zRAM ซึ่งจะได้รับการบีบอัด ซึ่งจะช่วยเพิ่มหน่วยความจำที่พร้อมใช้งานใน RAM (หน้าว่าง) หากกระบวนการพยายามเข้าถึงหน้าที่ยังไม่ได้เขียนลงใน zRAM ระบบจะยกเลิกการบีบอัดหน้านั้นและย้ายกลับไปยัง RAM หากกระบวนการที่เชื่อมโยงกับหน้าเว็บที่บีบอัดถูกยกเลิก ระบบจะลบหน้าเว็บออกจาก zRAM
หากจำนวนหน่วยความจำว่างลดลงต่ำกว่าเกณฑ์ที่กำหนด ระบบจะเริ่มฆ่ากระบวนการ
รูปที่ 3 ย้ายหน้าเว็บที่ยังไม่ได้บันทึกไปยัง zRAM และบีบอัด
โปรแกรมที่กินหน่วยความจำมาก
หลายครั้ง kswapd
ไม่สามารถเพิ่มหน่วยความจำให้กับระบบได้ ในกรณีนี้ ระบบจะใช้ onTrimMemory()
เพื่อแจ้งให้แอปทราบว่าหน่วยความจําเหลือน้อยและควรลดการจัดสรร หากยังไม่เพียงพอ เคอร์เนลจะเริ่มฆ่ากระบวนการเพื่อเพิ่มพื้นที่ว่างในหน่วยความจำ โดยจะใช้ Low-memory killer (LMK) ในการดำเนินการนี้
LMK ใช้คะแนน "หน่วยความจำไม่เพียงพอ" ที่ชื่อ oom_adj_score
เพื่อจัดลําดับความสําคัญของกระบวนการที่ทํางานอยู่เพื่อตัดสินใจว่าจะฆ่ากระบวนการใด ระบบจะหยุดกระบวนการที่มีคะแนนสูงก่อน แอปที่ทำงานอยู่เบื้องหลังจะถูกหยุดก่อน และกระบวนการของระบบจะถูกหยุดเป็นลำดับสุดท้าย ตารางต่อไปนี้แสดงหมวดหมู่การให้คะแนน LMK จากสูงไปต่ำ ระบบจะลบรายการในหมวดหมู่ที่มีคะแนนสูงสุดในแถวที่ 1 ออกก่อน
รูปที่ 4 กระบวนการของ Android โดยกระบวนการที่มีคะแนนสูงจะแสดงที่ด้านบนและกระบวนการที่มีคะแนนต่ำจะแสดงที่ด้านล่าง
คำอธิบายสำหรับหมวดหมู่ต่างๆ ในตารางด้านบนมีดังนี้
แอปที่ทำงานอยู่เบื้องหลัง: แอปที่ทำงานก่อนหน้านี้และไม่ได้ใช้งานอยู่ในขณะนี้ LMK จะปิดแอปเบื้องหลังก่อน โดยเริ่มจากแอปที่มี
oom_adj_score
สูงสุดแอปก่อนหน้า: แอปที่ทำงานอยู่เบื้องหลังซึ่งใช้งานล่าสุด แอปก่อนหน้าจะมีลําดับความสําคัญสูงกว่า (คะแนนต่ำกว่า) แอปที่ทำงานอยู่เบื้องหลัง เนื่องจากมีแนวโน้มว่าผู้ใช้จะเปลี่ยนไปใช้แอปก่อนหน้ามากกว่าแอปที่ทำงานอยู่เบื้องหลัง
แอป Home: แอปนี้เป็นแอปตัวเปิดแอป การปิดแอปนี้จะทำให้วอลเปเปอร์หายไป
บริการ: แอปพลิเคชันจะเริ่มต้นบริการและอาจรวมถึงการซิงค์หรืออัปโหลดไปยังระบบคลาวด์
แอปที่สังเกตได้: แอปที่ทำงานอยู่เบื้องหลังซึ่งผู้ใช้รับรู้ได้ เช่น การดำเนินการค้นหาที่แสดง UI ขนาดเล็กหรือการฟังเพลง
แอปที่ทำงานอยู่เบื้องหน้า: แอปที่ใช้งานอยู่ การสิ้นสุดการทำงานของแอปที่ทำงานอยู่เบื้องหน้าดูเหมือนว่าแอปพลิเคชันขัดข้อง ซึ่งอาจทำให้ผู้ใช้คิดว่าอุปกรณ์มีปัญหา
ถาวร (บริการ): บริการหลักสำหรับอุปกรณ์ เช่น โทรศัพท์และ Wi-Fi
ระบบ: กระบวนการของระบบ เมื่อกระบวนการเหล่านี้ถูกหยุด โทรศัพท์อาจดูเหมือนจะรีบูต
เนทีฟ: กระบวนการระดับต่ำมากที่ระบบใช้ (เช่น
kswapd
)
ผู้ผลิตอุปกรณ์สามารถเปลี่ยนลักษณะการทำงานของ LMK ได้
กำลังคำนวณหน่วยความจําที่ใช้
เคอร์เนลจะติดตามหน้าหน่วยความจำทั้งหมดในระบบ
รูปที่ 5 หน้าที่กระบวนการต่างๆ ใช้
เมื่อพิจารณาปริมาณหน่วยความจำที่แอปใช้อยู่ ระบบต้องพิจารณาถึงหน้าเว็บที่แชร์ด้วย แอปที่เข้าถึงบริการหรือคลังเดียวกันจะแชร์หน้าหน่วยความจำ เช่น บริการ Google Play และแอปเกมอาจแชร์บริการตำแหน่ง ซึ่งทำให้ระบุปริมาณหน่วยความจำของบริการโดยรวมเทียบกับแต่ละแอปพลิเคชันได้ยาก
รูปที่ 6 หน้าเว็บที่แชร์โดย 2 แอป (ตรงกลาง)
หากต้องการระบุพื้นที่หน่วยความจำของแอปพลิเคชัน คุณอาจใช้เมตริกใดก็ได้ต่อไปนี้
- Resident Set Size (RSS): จํานวนหน้าเว็บที่แชร์และไม่แชร์ที่แอปใช้
- ขนาดชุดตามสัดส่วน (PSS): จำนวนหน้าที่ไม่ได้แชร์ซึ่งแอปใช้และการกระจายหน้าที่แชร์อย่างสม่ำเสมอ (เช่น หากมี 3 กระบวนการแชร์ 3 MB แต่ละกระบวนการจะได้รับ PSS 1 MB)
- ขนาดชุดที่ไม่ซ้ำกัน (USS): จํานวนหน้าเว็บที่ไม่ได้แชร์ซึ่งแอปใช้ (ไม่รวมหน้าเว็บที่แชร์)
PSS มีประโยชน์ต่อระบบปฏิบัติการเมื่อต้องการทราบว่ามีการใช้หน่วยความจําเท่าใดโดยกระบวนการทั้งหมด เนื่องจากระบบจะไม่นับหน้าเว็บหลายครั้ง PSS จะใช้เวลานานในการคํานวณเนื่องจากระบบต้องพิจารณาว่าหน้าเว็บใดมีการแชร์และมีการแชร์กี่กระบวนการ RSS ไม่ได้แยกความแตกต่างระหว่างหน้าที่แชร์และไม่แชร์ (ทำให้คำนวณได้เร็วขึ้น) และเหมาะสําหรับการติดตามการเปลี่ยนแปลงในการกําหนดหน่วยความจํามากกว่า
แหล่งข้อมูลเพิ่มเติม
- ภาพรวมของการจัดการหน่วยความจํา
- กระบวนการและวงจรของแอปพลิเคชัน
- การทำความเข้าใจการใช้หน่วยความจำของ Android - งานนำเสนอ Google I/O
- Android Memory and Games - Google I/O presentation
- Android low memory killer daemon
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- เวลาเริ่มต้นของแอป