Daemon ที่จะหยุดแอปเมื่อหน่วยความจําเหลือน้อย

กระบวนการ Daemon ของตัวจัดการการหยุดทำงานเนื่องจากหน่วยความจำไม่เพียงพอ (lmkd) ของ Android จะตรวจสอบสถานะหน่วยความจำของระบบ Android ที่ทำงานอยู่ และตอบสนองต่อการใช้หน่วยความจำสูงด้วยการหยุดกระบวนการที่ไม่จำเป็นที่สุดเพื่อให้ระบบทำงานในระดับที่ยอมรับได้

เกี่ยวกับการใช้หน่วยความจำ

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

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

ข้อมูลการหยุดทำงานเนื่องจากการใช้หน่วยความจำ

Android 10 ขึ้นไปรองรับโหมด lmkd ใหม่ที่ใช้จอภาพข้อมูลการหยุดทำงานเนื่องจากการใช้หน่วยความจำ (PSI) ของเคอร์เนลเพื่อตรวจหาการใช้หน่วยความจำ ชุดแพตช์ PSI ในเคอร์เนลต้นน้ำ (ย้อนกลับไปยังเคอร์เนล 4.9 และ 4.14) จะวัดระยะเวลาที่งานล่าช้าเนื่องจากหน่วยความจำไม่เพียงพอ เนื่องจากความล่าช้าเหล่านี้ส่งผลต่อประสบการณ์ของผู้ใช้โดยตรง จึงเป็นเมตริกที่สะดวกในการกำหนดความรุนแรงของการใช้หน่วยความจำ เคอร์เนลต้นน้ำยังมีจอภาพ PSI ที่อนุญาตให้กระบวนการในพื้นที่ของผู้ใช้ที่มีสิทธิ์ (เช่น lmkd) ระบุเกณฑ์สำหรับความล่าช้าเหล่านี้และสมัครรับข้อมูลเหตุการณ์จากเคอร์เนลเมื่อมีการละเมิดเกณฑ์

จอภาพ PSI เทียบกับสัญญาณ `vmpressure`

เนื่องจากสัญญาณ vmpressure (ที่เคอร์เนลสร้างขึ้นเพื่อตรวจหาการใช้หน่วยความจำและ lmkd ใช้) มักจะมีผลบวกที่ผิดพลาดจำนวนมาก lmkd จึงต้องทำการกรองเพื่อพิจารณาว่าหน่วยความจำมีการใช้จริงหรือไม่ ซึ่งส่งผลให้ lmkd ตื่นขึ้นโดยไม่จำเป็นและใช้ทรัพยากรการคำนวณเพิ่มเติม การใช้จอภาพ PSI จะส่งผลให้ตรวจหาการใช้หน่วยความจำได้แม่นยำยิ่งขึ้นและลดค่าใช้จ่ายในการกรอง

ใช้จอภาพ PSI

หากต้องการใช้จอภาพ PSI แทนเหตุการณ์ vmpressure ให้กำหนดค่าพร็อพเพอร์ตี้ ro.lmk.use_psi ค่าเริ่มต้นคือ true ซึ่งทำให้จอภาพ PSI เป็นกลไกเริ่มต้นในการตรวจหาการใช้หน่วยความจำสำหรับ lmkd เนื่องจากจอภาพ PSI ต้องได้รับการรองรับจากเคอร์เนล เคอร์เนลจึงต้องมีแพตช์ย้อนกลับ PSI และคอมไพล์โดยเปิดใช้การรองรับ PSI (CONFIG_PSI=y)

ข้อเสียของไดรเวอร์ LMK ในเคอร์เนล

Android เลิกใช้งานไดรเวอร์ LMK เนื่องจากปัญหาหลายประการ ซึ่งรวมถึง

  • อุปกรณ์ที่มี RAM ต่ำต้องได้รับการปรับแต่งอย่างเข้มงวด และถึงอย่างนั้นก็ยังทำงานได้ไม่ดีในปริมาณงานที่มีแคชหน้าเว็บที่ใช้งานอยู่ซึ่งมีขนาดใหญ่ ประสิทธิภาพที่ไม่ดีส่งผลให้เกิดการ Thrash และไม่มีการหยุดทำงาน
  • ไดรเวอร์ LMK เคอร์เนลอาศัยขีดจำกัดหน่วยความจำที่ว่าง โดยไม่มีการปรับขนาดตามการใช้หน่วยความจำ
  • เนื่องจากการออกแบบที่เข้มงวด พาร์ทเนอร์จึงมักจะปรับแต่งไดรเวอร์เพื่อให้ทำงานในอุปกรณ์ของตนได้
  • ไดรเวอร์ LMK เชื่อมต่อกับ API ของตัวลดขนาด Slab ซึ่งไม่ได้ออกแบบมาสำหรับการดำเนินการที่หนักหน่วง เช่น การค้นหาเป้าหมายและการหยุดเป้าหมาย ซึ่งทำให้กระบวนการ vmscan ช้าลง

lmkd ในพื้นที่ของผู้ใช้

lmkd ในพื้นที่ของผู้ใช้จะใช้ฟังก์ชันการทำงานเดียวกันกับไดรเวอร์ในเคอร์เนล แต่ใช้กลไกของเคอร์เนลที่มีอยู่เพื่อตรวจหาและประมาณการใช้หน่วยความจำ กลไกดังกล่าวรวมถึงการใช้เหตุการณ์ vmpressure ที่เคอร์เนลสร้างขึ้นหรือจอภาพข้อมูลการหยุดทำงานเนื่องจากการใช้หน่วยความจำ (PSI) เพื่อรับการแจ้งเตือนเกี่ยวกับระดับการใช้หน่วยความจำ และใช้ฟีเจอร์ cgroup ของหน่วยความจำเพื่อจำกัดทรัพยากรหน่วยความจำที่จัดสรรให้กับแต่ละกระบวนการตามความสำคัญของกระบวนการ

ใช้ lmkd ในพื้นที่ของผู้ใช้ใน Android 10

ใน Android 9 ขึ้นไป lmkd ในพื้นที่ของผู้ใช้จะเปิดใช้งานหากไม่พบไดรเวอร์ LMK ในเคอร์เนล เนื่องจาก lmkd ในพื้นที่ของผู้ใช้ต้องได้รับการรองรับจากเคอร์เนลสำหรับ cgroup ของหน่วยความจำ เคอร์เนลจึงต้องคอมไพล์ด้วยการตั้งค่าการกำหนดค่าต่อไปนี้

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

กลยุทธ์การหยุดทำงาน

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

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

คุณสามารถกำหนดค่ากลยุทธ์การหยุดทำงานโดยใช้พร็อพเพอร์ตี้ ro.config.low_ram

lmkd ในพื้นที่ของผู้ใช้ยังรองรับโหมดเดิมซึ่งจะตัดสินใจหยุดทำงานโดยใช้กลยุทธ์เดียวกับไดรเวอร์ LMK ในเคอร์เนล (นั่นคือ ขีดจำกัดหน่วยความจำที่ว่างและแคชไฟล์) หากต้องการเปิดใช้โหมดเดิม ให้ตั้งค่าพร็อพเพอร์ตี้ ro.lmk.use_minfree_levels เป็น true

กำหนดค่า lmkd

กำหนดค่า lmkd สำหรับอุปกรณ์ที่เฉพาะเจาะจงโดยใช้พร็อพเพอร์ตี้ต่อไปนี้

พร็อพเพอร์ตี้ ใช้ ค่าเริ่มต้น
ro.config.low_ram ระบุว่าอุปกรณ์เป็นอุปกรณ์ที่มี RAM ต่ำหรืออุปกรณ์ที่มีประสิทธิภาพสูง false
ro.lmk.use_psi ใช้จอภาพ PSI (แทนเหตุการณ์ vmpressure) true
ro.lmk.use_minfree_levels ใช้ขีดจำกัดหน่วยความจำที่ว่างและแคชไฟล์เพื่อตัดสินใจหยุดกระบวนการ (นั่นคือ จับคู่ฟังก์ชันการทำงานของไดรเวอร์ LMK ในเคอร์เนล ) false
ro.lmk.low คะแนน oom_adj ขั้นต่ำสำหรับกระบวนการที่มีสิทธิ์หยุดทำงานที่ระดับ vmpressure ต่ำ 1001
(ปิดใช้)
ro.lmk.medium คะแนน oom_adj ขั้นต่ำสำหรับกระบวนการที่มีสิทธิ์หยุดทำงานที่ระดับ vmpressure ปานกลาง 800
(บริการที่แคชไว้หรือไม่จำเป็น)
ro.lmk.critical คะแนน oom_adj ขั้นต่ำสำหรับกระบวนการที่มีสิทธิ์หยุดทำงานที่ระดับ vmpressure วิกฤต 0
(กระบวนการใดก็ได้)
ro.lmk.critical_upgrade เปิดใช้การอัปเกรดเป็นระดับวิกฤต false
ro.lmk.upgrade_pressure `mem_pressure` สูงสุดที่ระดับจะได้รับการอัปเกรด เนื่องจากระบบกำลังสลับมากเกินไปmem_pressure 100
(ปิดใช้)
ro.lmk.downgrade_pressure `mem_pressure` ขั้นต่ำที่ระบบจะละเว้นเหตุการณ์ vmpressure เนื่องจากยังมีหน่วยความจำที่ว่างเพียงพอmem_pressure 100
(ปิดใช้)
ro.lmk.kill_heaviest_task หยุดงานที่มีสิทธิ์ที่หนักที่สุด (การตัดสินใจที่ดีที่สุด) เทียบกับงานที่มีสิทธิ์ใดก็ได้ (การตัดสินใจที่รวดเร็ว) false
ro.lmk.kill_timeout_ms ระยะเวลาเป็นมิลลิวินาทีหลังจากหยุดทำงานเมื่อจะไม่มีการหยุดทำงานเพิ่มเติม 0
(ปิดใช้)
ro.lmk.debug เปิดใช้บันทึกการแก้ไขข้อบกพร่อง lmkd false

ตัวอย่างการกำหนดค่าอุปกรณ์

PRODUCT_PROPERTY_OVERRIDES += \
    ro.lmk.low=1001 \
    ro.lmk.medium=800 \
    ro.lmk.critical=0 \
    ro.lmk.critical_upgrade=false \
    ro.lmk.upgrade_pressure=100 \
    ro.lmk.downgrade_pressure=100 \
    ro.lmk.kill_heaviest_task=true

lmkd ในพื้นที่ของผู้ใช้ใน Android 11

Android 11 ปรับปรุง lmkd โดยนำกลยุทธ์การหยุดทำงานใหม่มาใช้ กลยุทธ์การหยุดทำงานใช้กลไก PSI ในการตรวจหาการใช้หน่วยความจำที่เปิดตัวใน Android 10 lmkd ใน Android 11 จะพิจารณาระดับการใช้ทรัพยากรหน่วยความจำและการ Thrash เพื่อป้องกันการขาดแคลนหน่วยความจำและประสิทธิภาพลดลง กลยุทธ์การหยุดทำงานนี้จะแทนที่กลยุทธ์ก่อนหน้าและสามารถใช้ได้กับทั้งอุปกรณ์ที่มีประสิทธิภาพสูงและอุปกรณ์ที่มี RAM ต่ำ (Android Go)

ข้อกำหนดของเคอร์เนล

สำหรับอุปกรณ์ Android 11 lmkd ต้องมีฟีเจอร์เคอร์เนลต่อไปนี้

  • รวมแพตช์ PSI และเปิดใช้ PSI (การย้อนกลับมีอยู่ในเคอร์เนลทั่วไปของ Android 4.9, 4.14 และ 4.19)
  • รวมแพตช์การรองรับ PIDFD (การย้อนกลับมีอยู่ในเคอร์เนลทั่วไปของ Android 4.9, 4.14 และ 4.19)
  • สำหรับอุปกรณ์ที่มี RAM ต่ำ ให้รวม cgroup ของหน่วยความจำ

เคอร์เนลต้องคอมไพล์ด้วยการตั้งค่าการกำหนดค่าต่อไปนี้

CONFIG_PSI=y

กำหนดค่า lmkd ใน Android 11

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

พร็อพเพอร์ตี้ ใช้ ค่าเริ่มต้น
ประสิทธิภาพสูง RAM ต่ำ
ro.lmk.psi_partial_stall_ms เกณฑ์การหยุดทำงาน PSI บางส่วนเป็นมิลลิวินาทีสำหรับการทริกเกอร์การแจ้งเตือนหน่วยความจำไม่เพียงพอ หากอุปกรณ์ได้รับการแจ้งเตือนการใช้หน่วยความจำ ช้าเกินไป ให้ลดค่านี้เพื่อทริกเกอร์การแจ้งเตือนก่อนหน้านี้ หากการแจ้งเตือนการใช้หน่วยความจำ ทริกเกอร์โดยไม่จำเป็น ให้เพิ่มค่านี้เพื่อให้อุปกรณ์มีความไวต่อสัญญาณรบกวนน้อยลง 70 200
ro.lmk.psi_complete_stall_ms เกณฑ์การหยุดทำงาน PSI ทั้งหมดเป็นมิลลิวินาทีสำหรับการทริกเกอร์ การแจ้งเตือนหน่วยความจำวิกฤต หากอุปกรณ์ได้รับการแจ้งเตือนการใช้หน่วยความจำวิกฤตช้าเกินไป ให้ลดค่านี้เพื่อทริกเกอร์การแจ้งเตือนก่อนหน้านี้ หากการแจ้งเตือนการใช้หน่วยความจำวิกฤตทริกเกอร์ โดยไม่จำเป็น ให้เพิ่มค่านี้เพื่อให้อุปกรณ์มีความไวต่อ สัญญาณรบกวนน้อยลง 700
ro.lmk.thrashing_limit จำนวนสูงสุดของการเกิดข้อผิดพลาดซ้ำของชุดการทำงานเป็นเปอร์เซ็นต์ของขนาดแคชหน้าเว็บทั้งหมดที่สำรองด้วยไฟล์ การเกิดข้อผิดพลาดซ้ำของชุดการทำงานที่สูงกว่าค่านี้หมายความว่าระบบกำลังสลับหน้าเว็บ หากประสิทธิภาพของอุปกรณ์ได้รับผลกระทบระหว่างการใช้หน่วยความจำ ให้ลดค่าเพื่อจำกัดการ Thrash หากประสิทธิภาพของอุปกรณ์หยุดทำงาน โดยไม่จำเป็นเนื่องจากเหตุผลการ Thrash ให้เพิ่มค่าเพื่อให้มีการ Thrash มากขึ้น 100 30
ro.lmk.thrashing_limit_decay การลดลงของเกณฑ์การ Thrash แสดงเป็นเปอร์เซ็นต์ของเกณฑ์เดิมที่ใช้เพื่อลดเกณฑ์เมื่อระบบไม่กู้คืน แม้หลังจากหยุดทำงานแล้วก็ตาม หากการ Thrash อย่างต่อเนื่องทำให้เกิดการหยุดทำงานโดยไม่จำเป็น ให้ลดค่า หากการตอบสนองต่อการ Thrash อย่างต่อเนื่องหลังจาก หยุดทำงานช้าเกินไป ให้เพิ่มค่า 10 50
ro.lmk.swap_util_max หน่วยความจำที่สลับสูงสุดเป็นเปอร์เซ็นต์ของหน่วยความจำทั้งหมดที่สลับได้ เมื่อหน่วยความจำที่สลับเพิ่มขึ้นเกินขีดจำกัดนี้ หมายความว่าระบบได้สลับหน่วยความจำส่วนใหญ่ที่สลับได้และยังคงมีการใช้หน่วยความจำอยู่ กรณีนี้อาจเกิดขึ้นได้เมื่อการจัดสรรที่ไม่สามารถสลับได้ทำให้เกิดการใช้หน่วยความจำ ซึ่งไม่สามารถลดลงได้โดยการสลับเนื่องจากหน่วยความจำส่วนใหญ่ที่สลับได้ถูกสลับออกไปแล้ว ค่าเริ่มต้นคือ 100 ซึ่งจะปิดใช้การตรวจสอบนี้อย่างมีประสิทธิภาพ หากประสิทธิภาพของอุปกรณ์ได้รับผลกระทบระหว่าง การใช้หน่วยความจำในขณะที่การใช้ Swap สูงและระดับ Swap ที่ว่าง ไม่ลดลงเหลือ ro.lmk.swap_free_low_percentage ให้ลด ค่าเพื่อจำกัดการใช้ Swap 100 100

ปุ่มปรับแต่งเก่าต่อไปนี้ยังทำงานร่วมกับกลยุทธ์การหยุดทำงานใหม่ได้ด้วย

พร็อพเพอร์ตี้ ใช้ ค่าเริ่มต้น
ประสิทธิภาพสูง RAM ต่ำ
ro.lmk.swap_free_low_percentage ระดับ Swap ที่ว่างเป็นเปอร์เซ็นต์ของพื้นที่ Swap ทั้งหมด `lmkd` ใช้ค่านี้เป็นเกณฑ์ในการพิจารณาว่าระบบมีพื้นที่ Swap ไม่เพียงพอ หาก `lmkd` หยุดทำงานในขณะที่มีพื้นที่ Swap มากเกินไป ให้ลดเปอร์เซ็นต์ หาก `lmkd` หยุดทำงานช้าเกินไป ทำให้เกิดการหยุดทำงานเนื่องจากหน่วยความจำไม่เพียงพอ ให้เพิ่มเปอร์เซ็นต์ 20 10
ro.lmk.debug การดำเนินการนี้จะเปิดใช้บันทึกการแก้ไขข้อบกพร่อง `lmkd` เปิดใช้การแก้ไขข้อบกพร่องขณะปรับแต่ง false