ภูตนักฆ่าหน่วยความจำต่ำ

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

เกี่ยวกับหน่วยความจำความดัน

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

ในอดีต Android ได้ตรวจสอบความดันของหน่วยความจำระบบโดยใช้ไดรเวอร์ in-kernel low memory killer (LMK) ซึ่งเป็นกลไกที่เข้มงวดซึ่งขึ้นอยู่กับค่าฮาร์ดโค้ด ในฐานะของเคอร์เนล 4.12 ขับ LMK ถูกลบออกจากเคอร์เนลต้นน้ำและ userspace lmkd การตรวจสอบหน่วยความจำดำเนินการและขั้นตอนการฆ่างาน

ข้อมูลแผงความดัน

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

มอนิเตอร์ PSI กับสัญญาณ vmpressure

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

การใช้จอภาพ PSI

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

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

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

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

Userspace lmkd

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

การใช้พื้นที่ผู้ใช้ lmkd ใน Android 10

ใน Android 9 และต่อมา userspace lmkd เปิดใช้งานถ้าในเคอร์เนลไดรเวอร์ LMK ตรวจไม่พบ เพราะ userspace lmkd ต้องการการสนับสนุนโปรแกรมสำหรับ cgroups หน่วยความจำเคอร์เนลจะต้องรวบรวมกับการตั้งค่าดังต่อไปนี้:

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

กลยุทธ์การฆ่า

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

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

คุณสามารถกำหนดกลยุทธ์การฆ่าโดยใช้ ro.config.low_ram คุณสมบัติ (สำหรับรายละเอียดโปรดดูที่ การกำหนดค่า RAM ต่ำ )

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

การกำหนดค่า lmkd

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

คุณสมบัติ ใช้ ค่าเริ่มต้น
ro.config.low_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 ที่ระดับมีการปรับรุ่นเพราะระบบมีการแลกเปลี่ยนมากเกินไป 100
(พิการ)
ro.lmk.downgrade_pressure ขั้นต่ำ mem_pressure ที่ที่ vmpressure เหตุการณ์ถูกละเว้นเนื่องจากหน่วยความจำฟรีพอที่ยังคงมีอยู่ 100
(พิการ)
ro.lmk.kill_heaviest_task ฆ่างานที่มีสิทธิ์มากที่สุด (การตัดสินใจที่ดีที่สุด) กับงานที่มีสิทธิ์ (การตัดสินใจที่รวดเร็ว) true
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

Userspace lmkd ใน Android 11

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

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

สำหรับ Android 11 อุปกรณ์ lmkd ต้องการคุณลักษณะเคอร์เนลต่อไปนี้:

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

เคอร์เนลต้องถูกคอมไพล์ด้วยการตั้งค่าคอนฟิกูเรชันต่อไปนี้:

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 จำนวนสูงสุดของชุดการทำงานเริ่มต้นใหม่เป็นเปอร์เซ็นต์ของขนาดเพจแคชที่สำรองไฟล์ทั้งหมด ค่ารีฟอลต์ของ Workingset ที่สูงกว่าค่านี้หมายความว่าระบบจะถือว่าระบบกำลังโจมตี pagecache หากประสิทธิภาพของอุปกรณ์ได้รับผลกระทบระหว่างแรงดันหน่วยความจำ ให้ลดค่าลงเพื่อจำกัดการฟาด หากประสิทธิภาพของอุปกรณ์ถูกฆ่าโดยไม่จำเป็นด้วยเหตุผลการฟาดฟัน ให้เพิ่มค่าเพื่อให้มีการฟาดมากขึ้น 100 30
ro.lmk.thrashing_limit_decay การสลายตัวของ Thrashing Threshold แสดงเป็นเปอร์เซ็นต์ของเกณฑ์เดิมที่ใช้ในการลดเกณฑ์ขั้นต่ำเมื่อระบบไม่กู้คืน แม้หลังจากการฆ่า หากการฟาดฟันอย่างต่อเนื่องทำให้เกิดการฆ่าโดยไม่จำเป็น ให้ลดค่าลง หากการตอบสนองต่อการฟาดต่อเนื่องหลังจากการฆ่าช้าเกินไป ให้เพิ่มค่า 10 50
ro.lmk.swap_util_max จำนวนหน่วยความจำที่สลับสูงสุดเป็นเปอร์เซ็นต์ของหน่วยความจำที่สลับได้ทั้งหมด เมื่อหน่วยความจำที่สลับเพิ่มขึ้นเกินขีดจำกัดนี้ หมายความว่าระบบได้สลับหน่วยความจำที่สลับได้เกือบทั้งหมดและยังอยู่ภายใต้แรงกดดัน สิ่งนี้สามารถเกิดขึ้นได้เมื่อการจัดสรรที่ไม่สามารถสับเปลี่ยนได้ทำให้เกิดแรงกดดันในหน่วยความจำซึ่งไม่สามารถบรรเทาได้ด้วยการแลกเปลี่ยนเนื่องจากหน่วยความจำแบบถอดเปลี่ยนได้ส่วนใหญ่ถูกสลับออกแล้ว ค่าเริ่มต้นคือ 100 ซึ่งปิดใช้งานการตรวจสอบนี้อย่างมีประสิทธิภาพ ถ้าประสิทธิภาพของอุปกรณ์ที่ได้รับผลกระทบในช่วงความดันหน่วยความจำในขณะที่การใช้ประโยชน์แลกเปลี่ยนอยู่ในระดับสูงและระดับแลกเปลี่ยนฟรีไม่ได้หล่นลงไป ro.lmk.swap_free_low_percentage ลดค่าที่จะใช้ประโยชน์แลกเปลี่ยนขีด จำกัด 100 100

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

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