กระบวนการ daemon นักฆ่าหน่วยความจำต่ำ ( lmkd
) ของ Android จะตรวจสอบสถานะหน่วยความจำของระบบ 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
(สร้างโดยเคอร์เนลสำหรับการตรวจจับแรงดันหน่วยความจำและใช้โดย lmkd
) มักจะรวมผลบวกปลอมจำนวนมาก lmkd
จึงต้องทำการกรองเพื่อตรวจสอบว่าหน่วยความจำอยู่ภายใต้แรงกดดันจริงหรือไม่ ส่งผลให้เกิดการ lmkd
ที่ไม่จำเป็นและการใช้ทรัพยากรการคำนวณเพิ่มเติม การใช้มอนิเตอร์ PSI ส่งผลให้การตรวจจับแรงดันหน่วยความจำแม่นยำยิ่งขึ้น และลดค่าใช้จ่ายในการกรองให้เหลือน้อยที่สุด
การใช้จอภาพ PSI
เมื่อต้องการใช้การมอนิเตอร์ PSI แทนเหตุการณ์ vmpressure
ให้กำหนดคอนฟิกคุณสมบัติ ro.lmk.use_psi
ค่าดีฟอลต์คือ true
ทำให้ PSI มอนิเตอร์กลไกเริ่มต้นของการตรวจจับแรงดันหน่วยความจำสำหรับ lmkd
เนื่องจากมอนิเตอร์ PSI ต้องการการสนับสนุนเคอร์เนล เคอร์เนลจึงต้องรวมแพตช์ PSI backport และคอมไพล์ด้วยการเปิดใช้งานการรองรับ PSI ( CONFIG_PSI=y
)
ข้อเสียของไดรเวอร์ LMK ในเคอร์เนล
Android เลิกใช้ไดรเวอร์ LMK เนื่องจากปัญหาหลายประการ ได้แก่:
- อุปกรณ์ที่มี RAM ต่ำต้องได้รับการปรับแต่งอย่างจริงจัง และถึงกระนั้นก็ยังทำงานได้ไม่ดีกับปริมาณงานที่มีเพจแคชที่แอ็คทีฟสำรองไฟล์ขนาดใหญ่ ผลงานที่ย่ำแย่ส่งผลให้เกิดการฟาดฟันและไม่มีการสังหาร
- ไดรเวอร์เคอร์เนล LMK อาศัยขีดจำกัดหน่วยความจำฟรี ไม่มีการปรับขนาดตามแรงดันหน่วยความจำ
- เนื่องจากความแข็งแกร่งของการออกแบบ พันธมิตรจึงมักจะปรับแต่งไดรเวอร์เพื่อให้ทำงานบนอุปกรณ์ของพวกเขาได้
- ไดรเวอร์ LMK เชื่อมต่อกับ Slab Shrinker API ซึ่งไม่ได้ออกแบบมาสำหรับการใช้งานหนัก เช่น การค้นหาเป้าหมายและการฆ่า ซึ่งทำให้กระบวนการ
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
สำหรับรายละเอียด โปรดดู การกำหนดค่าแรมต่ำ
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 แสดงเป็นเปอร์เซ็นต์ของเกณฑ์เดิมที่ใช้ในการลด 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 |