การเพิ่มประสิทธิภาพหน่วยความจำเป็นสิ่งสำคัญในการมอบประสบการณ์การเล่นเกมที่เสถียรและมีประสิทธิภาพสูงบน Android คู่มือนี้จะอธิบายภาพรวมว่าทำไมประสิทธิภาพของหน่วยความจำจึงสำคัญ วิธีที่ระบบปฏิบัติการ Android จัดการขีดจำกัดหน่วยความจำของกระบวนการ และเมตริกหน่วยความจำใหม่ใน Google Play Console เพื่อช่วยคุณตรวจสอบและปรับปรุงคุณภาพทางเทคนิคของเกม
ความสำคัญของการเพิ่มประสิทธิภาพหน่วยความจำ
การเพิ่มประสิทธิภาพหน่วยความจำของเกมเป็นสิ่งสำคัญในการคงผู้เล่นไว้ ขยายความเข้ากันได้ของอุปกรณ์ และปฏิบัติตามมาตรฐานคุณภาพของแพลตฟอร์ม ดังนี้
- การป้องกันการเริ่มระบบใหม่ (ประสบการณ์ของผู้ใช้และการคงผู้ใช้ไว้): เมื่อผู้เล่นเปลี่ยนจากเกมของคุณไปทำอย่างอื่นชั่วคราว (เช่น ตอบการแจ้งเตือนหรือตรวจสอบข้อความ) ระบบปฏิบัติการจะย้ายกระบวนการของเกมไปไว้ในเบื้องหลัง หากหน่วยความจำที่ใช้ในเบื้องหลังของเกมสูงเกินไป Low Memory Killer (LMK) ของระบบจะจัดลำดับความสำคัญของการสิ้นสุดกระบวนการของเกมเพื่อเรียกคืน RAM สำหรับงานที่ทำงานอยู่เบื้องหน้า ครั้งถัดไปที่ผู้ใช้กลับมาเล่นเกมต่อ แทนที่จะเป็นการกลับมาเล่นต่อแบบอุ่นเครื่องที่ราบรื่นและรวดเร็ว เกมจะต้องผ่านการเริ่มใหม่แบบเย็นที่ใช้เวลานาน ซึ่งจะโหลดเนื้อหากราฟิก เสียง และไบนารีของเกมเอนจินที่มีขนาดใหญ่อีกครั้งทั้งหมดจากพื้นที่เก็บข้อมูล การรักษาการใช้งานหน่วยความจำในเบื้องหลังให้ต่ำจะช่วยป้องกันการสิ้นสุดการทำงานในเบื้องหลังโดยไม่แจ้งให้ทราบ ซึ่งจะช่วยรักษาสถานะของผู้ใช้และทำให้ผู้เล่นกลับมาเล่นต่อได้ทันที ดูรายละเอียดเพิ่มเติมเกี่ยวกับลักษณะการทำงานของ LMK ของระบบได้ที่คู่มือ Android Vitals - ตัวปิดแอปเมื่อหน่วยความจำเหลือน้อย
- ความเสถียรของระบบนิเวศและอุปกรณ์: การใช้งานหน่วยความจำที่ไม่มีประสิทธิภาพและหน่วยความจำรั่วไหลจะทำให้ประสิทธิภาพโดยรวมของระบบลดลง เมื่อหน่วยความจำระบบเหลือน้อย ระบบจะเผชิญกับแรงกดดันอย่างรุนแรง ส่งผลให้อัตราเฟรมลดลง UI กระตุก และเสียงขัดข้อง หากแรงกดดันของหน่วยความจำรุนแรงเกินไป Low Memory Killer (LMK) ของระบบจะสิ้นสุดกระบวนการเบื้องหลังอย่างรุนแรง ซึ่งจะบังคับให้แอปพลิเคชันอื่นๆ ประสบปัญหาการเริ่มทำงานใหม่แบบเย็นที่ช้าและสถานะผู้ใช้สูญหายเมื่อผู้เล่นสลับระหว่างงาน
- การสิ้นสุดการทำงานที่ระดับแพลตฟอร์ม: ตั้งแต่ Android 17 (ระดับ API 37) เป็นต้นไป ระบบจะดำเนินการเชิงรุกมากขึ้นในการสิ้นสุดกระบวนการที่ใช้หน่วยความจำมากเกินไป หากเกมใช้ทรัพยากรมากเกินไป ระบบปฏิบัติการอาจสิ้นสุดกระบวนการของเกมอย่างกะทันหันโดยไม่สร้างสแต็กเทรซมาตรฐาน
- ความเข้ากันได้ของอุปกรณ์: แม้อุปกรณ์เรือธงจะมี RAM ขนาด 12 GB ถึง 16 GB แต่ผู้เล่นเกมทั่วโลกจำนวนมากใช้อุปกรณ์ที่มี RAM ขนาด 4 GB หรือ 6 GB การจัดการหน่วยความจำที่เหมาะสมช่วยให้มั่นใจได้ว่าเกมของคุณจะยังคงเข้าถึงได้และตอบสนองได้ดีในฮาร์ดแวร์ทุกระดับโดยไม่ต้องใช้แพ็กเกจเนื้อหาที่ซับซ้อนและแยกต่างหาก
ทำความเข้าใจหน่วยความจำใน Android
ในการออกแบบกลยุทธ์การจัดสรรงบประมาณหน่วยความจำที่มีประสิทธิภาพ นักพัฒนาแอปต้องเข้าใจวิธีที่แพลตฟอร์ม Android จัดการหน่วยความจำกายภาพและวิธีวัดพื้นที่ทำงานที่ใช้งานอยู่ของเกม
แนวคิดหลักเกี่ยวกับหน่วยความจำของ Android
ดูแนวคิดพื้นฐานเกี่ยวกับการจัดการหน่วยความจำระดับแพลตฟอร์มได้ในเอกสารประกอบภาพรวมการจัดการหน่วยความจำอย่างเป็นทางการ แหล่งข้อมูลนี้ครอบคลุมสถาปัตยกรรม 4 ด้าน ได้แก่
- ภาพรวมของหน่วยความจำ: Android ใช้การแบ่งหน้าและการแมปหน่วยความจำ (mmap) เพื่อจัดการ RAM โดยไม่รองรับไฟล์สลับแบบดั้งเดิมในดิสก์ แต่จะอาศัยการบีบอัดหน้า (โดยใช้ zRAM) และการเรียกคืนหน้าเพื่อเพิ่มพื้นที่ว่างในหน่วยความจำจริง
- การจัดสรรหน่วยความจำระหว่างกระบวนการต่างๆ: Android แชร์ RAM ไปทั่วทั้งระบบ โดยจะกำหนดฮีปที่เฉพาะเจาะจงสำหรับการเรียกใช้เครื่องเสมือน Dalvik หรือ ART ขณะเดียวกันก็อนุญาตให้สภาพแวดล้อมในการพัฒนาซอฟต์แวร์แบบเนทีฟ (เช่น เกมเอนจิน C++) ขอหน่วยความจำจากฮีประบบแบบเนทีฟได้
- การจัดการหน่วยความจำของแอป: Android ทำงานภายใต้โมเดลแบบหลายกระบวนการ โดยคาดหวังให้แอปพลิเคชันตรวจสอบสถานะวงจรของตนเองแบบไดนามิกและปล่อยทรัพยากรที่ไม่จำเป็น (เช่น กราฟิกและบิตแมปที่ไม่ได้แคช) โดยสมัครใจเพื่อสนับสนุนประสิทธิภาพของระบบ
- ภาพรวมของกระบวนการและชุดข้อความ: ระบบจะจัดหมวดหมู่กระบวนการเป็นลำดับชั้นตามระดับการมองเห็นและความสำคัญที่ผู้ใช้รับรู้ในปัจจุบัน โดยจะกำหนดว่ากระบวนการใดจะยังคงทำงานอยู่และกระบวนการใดจะสิ้นสุดก่อนในสภาวะที่หน่วยความจำเหลือน้อย
เมตริกหน่วยความจำที่ใช้ทั้งหมด
ตัวจำกัดหน่วยความจำ Android 17 ระดับแพลตฟอร์มจะประเมินการใช้กระบวนการโดยใช้หน่วยความจำที่ใช้ทั้งหมดแทนขนาด Resident ทั้งหมด (RSS) หรือขนาดหน่วยความจำเสมือน
หน่วยความจำที่ใช้ทั้งหมด = RSS แบบไม่ระบุตัวตน (RssAnon) + Swap ที่ไม่บีบอัด (VmSwap)
คุณต้องเข้าใจอย่างถ่องแท้ว่าเมตริกเหล่านี้แสดงถึงอะไรในระดับระบบ เพื่อป้องกันไม่ให้เกมเกินขีดจำกัดของแพลตฟอร์ม ดูข้อมูลเพิ่มเติมเกี่ยวกับเมตริกเหล่านี้ การจัดสรร RAM จริง และวิธีจัดการหน้าเว็บที่ใช้ไฟล์เป็นแบ็กอัปได้ที่หัวข้อทำความเข้าใจเมตริก RSS และสลับในคู่มือตรวจสอบการใช้งานหน่วยความจำ
ข้อจำกัดด้านหน่วยความจำ
แพลตฟอร์ม Android จะจัดการขีดจำกัดหน่วยความจำสำหรับกระบวนการที่ทำงานอยู่เพื่อรักษาความเสถียรของระบบและตรวจสอบว่าแอปพลิเคชันไม่ใช้ทรัพยากรมากเกินไป
ตัวจำกัดหน่วยความจำใน Android 17 ขึ้นไป
Android 17 (ระดับ API 37) ขึ้นไปจะจัดการขีดจำกัดหน่วยความจำที่เข้มงวดต่อแอปโดยใช้ Linux cgroup v2 เพื่อป้องกันไม่ให้แอปแต่ละแอปทำให้ระบบไม่เสถียรทั้งระบบ ดูรายละเอียดเพิ่มเติมเกี่ยวกับการใช้งานทางเทคนิคได้ที่คู่มือตัวจำกัดหน่วยความจำของ AOSP และบล็อกการให้ความสำคัญกับประสิทธิภาพการใช้หน่วยความจำ: ขั้นตอนสำคัญสำหรับ Android 17
- กลไก: ตัวจำกัดหน่วยความจำจะตรวจสอบกระบวนการทั้งหมดของแอปพลิเคชันและกำหนดขีดจำกัดแบบไดนามิกตามสถานะวงจรของกระบวนการ ดังนี้
- กระบวนการที่มองเห็นได้ (เบื้องหน้า): กระบวนการของแอปที่กำลังแสดง UI คาดว่าจะเรียกใช้ชุดการทำงานของทรัพยากรที่ใหญ่ขึ้น และได้รับขีดจำกัดที่มากขึ้น
- กระบวนการที่มองไม่เห็น (เบื้องหลังหรือบริการ): กระบวนการของแอปที่ทำงานอยู่โดยไม่แสดง UI จะถูกจำกัดให้ใช้โควต้าที่เข้มงวดและจำกัดมากขึ้น
- แอตทริบิวต์เคอร์เนล: บริการนี้อาศัยแอตทริบิวต์หลัก 2 รายการ ได้แก่
memory.high: ขีดจำกัดแบบยืดหยุ่น เมื่อเกินขีดจำกัด เคอร์เนลจะควบคุมกระบวนการและพยายามเรียกคืนหน่วยความจำอย่างจริงจัง การเรียกคืนนี้อาจทำให้เกมมีประสิทธิภาพลดลงmemory.swap.max: จัดการขีดจำกัดสูงสุดของพื้นที่สลับหรือ zRAM ที่กระบวนการใช้ได้
- ลักษณะการสิ้นสุดการทำงาน: หากกระบวนการยังคงจัดสรรหน่วยความจำแบบไม่ระบุชื่อเกิน
memory.highและใช้ความจุสวอปจนหมด การจัดสรรจะล้มเหลว และระบบปฏิบัติการจะหยุดกระบวนการโดยไม่แจ้งให้ทราบ ระบบจะบันทึกการสิ้นสุดนี้โดยใช้ApplicationExitInfoภายใต้เหตุผลการออก Memory Limiter (พร้อมใช้งานตั้งแต่ Android 17, 26Q4 เป็นต้นไป)
ขีดจำกัดหน่วยความจำใหม่ใน Vitals ของ Play Console
Google Play ขอแนะนำเมตริกใหม่ใน Android Vitals ของ Play Console เพื่อช่วยให้นักพัฒนาแอประบุปัญหาเกี่ยวกับหน่วยความจำในเชิงรุกได้ Play Console จะติดตามหน่วยความจำที่ใช้ของ Anonymous RSS + Swap ในเปอร์เซ็นไทล์ที่ 90 (P90) ของเซสชันเกมเพื่อระบุค่าผิดปกติที่รุนแรง
เกณฑ์คำเตือนและการบังคับใช้จะปรับขนาดตามความจุ RAM จริงของอุปกรณ์และสถานะกระบวนการ ขีดจำกัดเหล่านี้จะมีผลใน 2 ระยะที่แตกต่างกัน
ดูหลักเกณฑ์โดยละเอียดและขีดจำกัดหน่วยความจำได้ที่ Android Vitals - "เกณฑ์ลักษณะการทำงานที่ไม่ถูกต้องคืออะไร"
บริการที่ผู้ใช้รับรู้
บริการที่รับรู้ได้คือกระบวนการเบื้องหลังที่สำคัญซึ่งระบบ Android ถือว่าผู้ใช้สังเกตเห็นได้ สถานะนี้ครอบคลุมกระบวนการทั้งหมดที่ทำงานอยู่ ดังนี้
- บริการที่ทำงานอยู่เบื้องหน้า (FGS)
- งานด่วน
- งานการโอนข้อมูลที่เริ่มต้นโดยผู้ใช้
- บริการที่มีผลผูกพันกับระบบหรือบริการที่มีผลผูกพันกับแอปพลิเคชันอื่นๆ
เนื่องจากบริการที่รับรู้ได้ออกแบบมาสำหรับงานที่สำคัญและใช้เวลานานในเบื้องหลัง จึงมีความเสี่ยงสูงที่จะเกิดการรั่วไหลของวงจรสะสม ขีดจำกัดหน่วยความจำของแพลตฟอร์ม Android จะถือว่าสถานะนี้ไม่ใช่เบื้องหน้า ซึ่งหมายความว่าหากเกมของคุณทำงานอยู่เบื้องหลังแต่ยังคงเรียกใช้บริการที่รับรู้ได้ เกมจะอยู่ภายใต้ขีดจำกัดหน่วยความจำของเบื้องหลังหรือบริการที่เข้มงวดขึ้นตามที่แสดงในหน้าศูนย์ช่วยเหลือของ Play เกมต้องตัดชิ้นงานที่ไม่จำเป็นออกอย่างจริงจังเมื่อย้ายจากเบื้องหน้าไปยังสถานะบริการที่รับรู้ได้ในเบื้องหลัง
ข้อกำหนดของ R8
Google Play Console จะประเมินการเพิ่มประสิทธิภาพโค้ดโดยเป็นส่วนหนึ่งของหลักเกณฑ์ด้านคุณภาพแอป เพื่อลดขนาดไบต์โค้ดและลดค่าใช้จ่ายในการประมวลผล Java พื้นฐาน ดูข้อมูลเพิ่มเติมเกี่ยวกับข้อกำหนดและขีดจำกัดการเพิ่มประสิทธิภาพที่ใช้กับเกมได้ที่การเพิ่มประสิทธิภาพโค้ด DEX ในเอกสารประกอบของ Android Vitals
หากต้องการกำหนดค่า R8 ในโปรเจ็กต์ Android มาตรฐาน ให้ทำตามคำแนะนำในหัวข้อเปิดใช้การเพิ่มประสิทธิภาพแอป หากต้องการเปิดใช้การตั้งค่าการลดขนาดและการเพิ่มประสิทธิภาพขั้นสูง โปรดดูหัวข้อใช้ R8 ในโหมดเต็ม หากต้องการระบุกฎที่ป้องกันไม่ให้ R8 สร้างความสับสนให้กับคลาสหรือนำโค้ดที่ไม่ได้ใช้งานออก ให้ใช้เครื่องมือวิเคราะห์การกำหนดค่า R8
หากคุณสร้างด้วยเกมเอนจิน ลักษณะการทำงานเริ่มต้นของ R8 จะแตกต่างกันไปตามเอนจินและเวอร์ชัน ดังนี้
- Unity: การลดขนาดโค้ดจะปิดอยู่โดยค่าเริ่มต้น คุณจึงต้องเปิดใช้ในการตั้งค่าโปรเจ็กต์ ดูข้อมูลเพิ่มเติมเกี่ยวกับการรองรับเวอร์ชันและขั้นตอนการกำหนดค่าได้ที่หัวข้อลดขนาดและเพิ่มประสิทธิภาพโค้ด Unity ด้วย R8
- Unreal Engine: ตั้งแต่ UE 4.25 เป็นต้นไป ระบบจะเปิดใช้ R8 โดยค่าเริ่มต้นในบิลด์ที่เผยแพร่ ซึ่งกำหนดให้คุณต้องจัดการกฎการเก็บรักษาสำหรับบริดจ์และปลั๊กอิน JNI ดูข้อมูลเพิ่มเติมเกี่ยวกับรายละเอียดเวอร์ชันและการกำหนดค่า UPL ได้ที่ลดขนาดและเพิ่มประสิทธิภาพโค้ด Unreal Engine ด้วย R8
ข้อกำหนดของบิตแมป
บิตแมปเป็นส่วนสำคัญของการใช้งานหน่วยความจำในเกมสมัยใหม่ที่มีความแม่นยำสูง เนื่องจากข้อมูลพิกเซลบิตแมปจะจัดเก็บไว้ในฮีปเนทีฟที่ไม่มีการจัดการโดยตรงใน Android 8.0 (ระดับ API 26) ขึ้นไป การโหลดรูปภาพที่ไม่ได้เพิ่มประสิทธิภาพจึงอาจทำให้กระบวนการต่างๆ เกินเกณฑ์หน่วยความจำของแพลตฟอร์มได้ ดูแนวทางปฏิบัติแนะนำเกี่ยวกับการปรับขนาดรูปภาพและการแคชได้ที่หัวข้อเพิ่มประสิทธิภาพการใช้รูปภาพ
ตรวจสอบการใช้งานหน่วยความจำ
หากต้องการเพิ่มประสิทธิภาพหน่วยความจำของเกมอย่างมีประสิทธิภาพ คุณต้องเข้าใจก่อนว่าแพลตฟอร์ม Android วัดขนาดของหน่วยความจำอย่างไร Android 17 อัปเดตเมตริกหน่วยความจำเพื่อติดตามผลรวมของ RSS แบบไม่ระบุตัวตน (RssAnon) และ Swap ที่ไม่บีบอัด (VmSwap) โดยไม่รวมหน่วยความจำที่สำรองไว้ในไฟล์หรือหน่วยความจำส่วนตัวของ GPU คู่มือนี้จะอธิบายรายละเอียดเกี่ยวกับวิธีใช้เครื่องมือระดับระบบ เช่น Perfetto และ meminfo, ใช้ API การวินิจฉัย เช่น ProfilingManager และ onTrimMemory รวมถึงดึงข้อมูลการจัดสรรหน่วยความจำที่แม่นยำภายใน Unity และ Unreal Engine ทำความเข้าใจวิธีสร้างโปรไฟล์เกมอย่างถูกต้องและหลีกเลี่ยงการกระตุกของประสิทธิภาพที่เกี่ยวข้องกับการโพลหน่วยความจำรันไทม์แบบดั้งเดิม
โปรดดูข้อมูลเพิ่มเติมที่หัวข้อตรวจสอบการใช้งานหน่วยความจำ
กลยุทธ์การลดหน่วยความจำ
แม้ว่าเกมเอนจินจะช่วยลดความซับซ้อนในการพัฒนาข้ามแพลตฟอร์ม แต่การจัดการหน่วยความจำเริ่มต้นของเกมเอนจินอาจทำให้เกิดขีดจำกัดหน่วยความจำระดับระบบปฏิบัติการ หน้านี้จะอธิบายขั้นตอนการเพิ่มประสิทธิภาพที่ใช้ได้จริงซึ่งปรับแต่งมาเพื่อ Unity และ Unreal Engine โดยเฉพาะ ทำความเข้าใจว่าเหตุใดการใช้ onTrimMemory ที่ใช้ Java จึงอาจทำให้เกิด Deadlock ใน Unity และวิธีใช้ Lifecycle Callback แบบเนทีฟแทน นอกจากนี้ คุณยังจะได้ทราบถึงการเพิ่มประสิทธิภาพที่สำคัญในระดับชิ้นงาน เช่น การใช้การบีบอัดพื้นผิว ASTC 8x8 และการกำหนดค่าการยกเลิกการโหลดชิ้นงาน เพื่อให้เกมทำงานได้อย่างราบรื่นในฮาร์ดแวร์ทุกระดับ
ดูข้อมูลเพิ่มเติมได้ที่ลดการใช้งานหน่วยความจำ