Android 17 ขึ้นไปรองรับตัวจำกัดหน่วยความจำ ซึ่งเป็นบริการของระบบที่ตรวจสอบและจำกัดการใช้งานหน่วยความจำของกระบวนการแอปพลิเคชันโดยใช้ cgroup v2 ของ Linux ตัวจำกัดหน่วยความจำจะป้องกันไม่ให้แอปแต่ละแอปใช้หน่วยความจำของระบบมากเกินไป ซึ่งจะช่วยลดแรงกดดันด้านหน่วยความจำทั่วทั้งระบบและป้องกันการหยุดกระบวนการที่สำคัญอย่างรุนแรงเนื่องจากหน่วยความจำไม่เพียงพอ (OOM)
กลไก
ตัวจำกัดหน่วยความจำจะผสานรวมกับบริการ Activity Manager (AMS) เพื่อติดตามเหตุการณ์วงจรการทำงานของกระบวนการและการเปลี่ยนแปลงสถานะ ตัวจำกัดหน่วยความจำจะบังคับใช้ขีดจำกัดหน่วยความจำโดยใช้ระบบไฟล์ cgroup v2 ของเคอร์เนล Linux
หากต้องการใช้ตัวจำกัดหน่วยความจำ เคอร์เนลของอุปกรณ์ต้องรองรับ cgroup v2 และตัวควบคุม memory บริการนี้อาศัยแอตทริบิวต์ต่อไปนี้โดยเฉพาะ
memory.high- ขีดจำกัดแบบไม่เข้มงวด เมื่อเกินขีดจำกัด กระบวนการจะถูกจำกัดความเร็วและเคอร์เนลจะพยายามเรียกคืนหน่วยความจำจากกระบวนการนั้น
memory.swap.max- จำกัดปริมาณพื้นที่สวอปที่กระบวนการใช้ได้
ผลกระทบต่อแอป
แอปที่ไม่เกินขีดจำกัดหน่วยความจำจะไม่ได้รับผลกระทบจากตัวจำกัดหน่วยความจำ
เมื่อแอปเกินขีดจำกัด memory.high เคอร์เนลจะนำหน่วยความจำที่สำรองไว้ในไฟล์ของแอปออกและสวอปหน่วยความจำที่ไม่ระบุชื่อออกเพื่อให้แอปอยู่ในขีดจำกัด การนำออกและการสวอปอาจทำให้แอปทำงานช้าลง
ในกรณีที่ร้ายแรงที่สุด หากแอปยังคงจัดสรรหน่วยความจำที่ไม่ระบุชื่อและอุปกรณ์มีพื้นที่สวอปไม่เพียงพอ แอปอาจจัดสรรหน่วยความจำไม่สำเร็จและมีแนวโน้มที่จะหยุดทำงาน
การตรวจสอบกระบวนการ
ตัวจำกัดหน่วยความจำจะตรวจสอบกระบวนการของแอป (UID >= 10000) โดยค่าเริ่มต้น โดยทั่วไปแล้วกระบวนการของระบบจะได้รับการยกเว้นเพื่อช่วยยืนยันความเสถียรของระบบหลัก
ตัวจำกัดหน่วยความจำจะกำหนดขีดจำกัดหน่วยความจำตามสถานะของกระบวนการ ดังนี้
กระบวนการที่แสดง คือกระบวนการที่ผู้ใช้รับรู้ได้ เช่น กิจกรรมเบื้องหน้า บริการเบื้องหน้า หรือสถานะอื่นๆ ที่ผู้ใช้รับรู้ได้ว่ามีการกระตุก
กระบวนการที่ไม่แสดง คือกระบวนการเบื้องหลังที่ไม่ได้โต้ตอบกับผู้ใช้หรือผู้ใช้มองไม่เห็น
ตารางต่อไปนี้แสดงการจับคู่สถานะกระบวนการที่เฉพาะเจาะจงกับขีดจำกัดหน่วยความจำ
| สถานะกระบวนการ | ขีดจำกัดหน่วยความจำ |
|---|---|
PERSISTENT | ไม่จำกัด |
PERSISTENT_UI | ไม่จำกัด |
TOP | แสดง |
BOUND_TOP | แสดง |
FOREGROUND_SERVICE | ไม่แสดง |
BOUND_FOREGROUND_SERVICE | ไม่แสดง |
IMPORTANT_FOREGROUND | แสดง |
IMPORTANT_BACKGROUND | ไม่แสดง |
TRANSIENT_BACKGROUND | ไม่แสดง |
BACKUP | ไม่แสดง |
SERVICE | ไม่แสดง |
RECEIVER | ไม่แสดง |
TOP_SLEEPING | แสดง |
HEAVY_WEIGHT | ไม่แสดง |
HOME | ไม่แสดง |
LAST_ACTIVITY | ไม่แสดง |
CACHED_ACTIVITY | แคชไว้ |
CACHED_ACTIVITY_CLIENT | แคชไว้ |
CACHED_RECENT | แคชไว้ |
CACHED_EMPTY | แคชไว้ |
ในสถานะแคช กระบวนการจะถูกระงับและเรียกคืนหน่วยความจำสูงสุด
เมื่อกระบวนการเกินขีดจำกัด memory.high ที่กำหนด ตัวจำกัดหน่วยความจำจะตรวจพบเหตุการณ์และสามารถทริกเกอร์การดำเนินการดีบัก เช่น การบันทึกโปรไฟล์หน่วยความจำหรือบันทึกความผิดปกติลงใน statsd
การกำหนดค่า
กำหนดค่าตัวจำกัดหน่วยความจำโดยใช้ไฟล์ XML ที่อยู่ในพาร์ติชัน vendor การกำหนดค่าช่วยให้คุณปรับขีดจำกัดหน่วยความจำสัมบูรณ์ตามข้อจำกัดหน่วยความจำที่เฉพาะเจาะจงของอุปกรณ์ได้
เส้นทางไฟล์:
/vendor/etc/memory-limiter-config.xmlการกำหนดค่าเริ่มต้น: หากไม่พบไฟล์การกำหนดค่า หรือหากอ่านไม่ได้หรือไม่ถูกต้อง ตัวจำกัดหน่วยความจำจะถูกปิดใช้
รูปแบบ XML
ไฟล์การกำหนดค่าเป็นไปตามสคีมาที่กำหนดไว้ใน memory-limiter-config.xsd ไฟล์นี้ช่วยให้คุณกำหนดชุดขีดจำกัดได้หลายชุด โดยบริการจะเลือกชุดที่เหมาะสมที่สุดตาม RAM ที่พร้อมใช้งานของอุปกรณ์ ค่าหน่วยความจำทั้งหมดจะกำหนดเป็นหน่วยเมบิไบต์ (MiB)
<MemoryLimiterConfig>
<version>1</version>
<configList>
<limitSet>
<!-- Limits for a phone with at least 14G of ram: 8G/4G/4G/4G -->
<minimumRequiredMemTotal>14336</minimumRequiredMemTotal>
<memVisible>8192</memVisible>
<memNotVisible>4096</memNotVisible>
<swapVisible>4096</swapVisible>
<swapNotVisible>4096</swapNotVisible>
</limitSet>
</configList>
</MemoryLimiterConfig>
version- จำนวนเต็มบวกที่ระบุเวอร์ชันการกำหนดค่า ซึ่งต้องเป็น 1
minimumRequiredMemTotal- หน่วยความจำของระบบที่พร้อมใช้งานขั้นต่ำที่จำเป็นเพื่อให้ชุดขีดจำกัดนี้ถูกต้อง
memVisible- ขีดจำกัดหน่วยความจำ (
memory.high) ที่อนุญาตสำหรับกระบวนการที่แสดง memNotVisible- ขีดจำกัดหน่วยความจำ (
memory.high) ที่อนุญาตสำหรับกระบวนการที่ไม่แสดง swapVisible- ขีดจำกัดการสวอป (
memory.swap.max) ที่อนุญาตสำหรับกระบวนการที่แสดง swapNotVisible- ขีดจำกัดการสวอป (
memory.swap.max) ที่อนุญาตสำหรับกระบวนการที่ไม่แสดง
แก้ไขการกำหนดค่า
หากต้องการเปลี่ยนขีดจำกัดทั่วทั้งระบบ ให้ทำตามขั้นตอนต่อไปนี้
- แก้ไข
/vendor/etc/memory-limiter-config.xml - รีบูตอุปกรณ์หรือรีสตาร์ท
system_serverเพื่อให้การเปลี่ยนแปลงมีผล
คำสั่ง Shell
คำสั่ง am memory-limiter ช่วยให้คุณและนักพัฒนาแอปโต้ตอบกับบริการได้ในขณะรันไทม์เพื่อการพัฒนาและการทดสอบ
am memory-limiter <SUB-COMMAND>สถานะ
คำสั่งย่อย status จะรายงานสถานะการทำงานของตัวจำกัดหน่วยความจำ
adb shell am memory-limiter statusตัวอย่างเอาต์พุต
Memory limiter
enabled monitoring=true ignored=none
visibleMem=1948MB visibleSwap=974MB
notVisibleMem=974MB notVisibleSwap=487MB
started=36 watched=36 watch-failed=0
events=0 processes=36 process-hwm=36
ฟิลด์สำคัญในเอาต์พุต ได้แก่
monitoring- ระบุว่าตัวจำกัดกำลังตรวจสอบกระบวนการอยู่หรือไม่
visibleMemและnotVisibleMem- ระบุขีดจำกัดหน่วยความจำสัมบูรณ์ที่คำนวณได้สำหรับแต่ละสถานะ
events- จำนวนครั้งที่กระบวนการเกินขีดจำกัด
processes- จำนวนกระบวนการที่ตรวจสอบ
ไม่สนใจ
คำสั่งย่อย ignore จะยกเว้น UID หรือกระบวนการทั้งหมดชั่วคราวไม่ให้ถูกจำกัด การดำเนินการนี้มีประโยชน์สำหรับการทดสอบประสิทธิภาพหรือเมื่อต้องการอนุญาตให้แอปที่เฉพาะเจาะจงเกินขีดจำกัด
adb shell am memory-limiter ignore 10087 // Ignore a specific UIDadb shell am memory-limiter ignore all // Ignore all processes (effectively disables limiting)adb shell am memory-limiter ignore none // Resume normal operation
ด้วยตนเอง
คำสั่งย่อย manual จะลบล้างขีดจำกัดที่คำนวณได้สำหรับกระบวนการที่เฉพาะเจาะจง (ตามรหัสกระบวนการหรือ PID) ด้วยค่าสัมบูรณ์ที่กำหนดเองในหน่วยเมกะไบต์ (MB) โดยทำดังนี้
adb shell am memory-limiter manual 1234 1024 // Set a 1024 MB limit for PID 1234adb shell am memory-limiter manual 1234 none // Remove the manual override for PID 1234
การลบล้างด้วยตนเองจะมีผลกับวงจรการทำงานของกระบวนการเท่านั้น หากกระบวนการรีสตาร์ท ระบบจะกลับไปใช้ขีดจำกัดเริ่มต้นตามสถานะของกระบวนการ