จัดการความจำอย่างมีประสิทธิภาพในเกม

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

หน้านี้จะอธิบายขั้นตอนที่คุณสามารถทำได้เพื่อหลีกเลี่ยงสภาวะหน่วยความจำเหลือน้อย ที่ส่งผลต่อเกม

ตอบสนองต่อ onTrimMemory()

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

หากระบบปิดแอปของคุณในเบื้องหลัง ครั้งถัดไปที่ผู้ใช้เปิดแอป ของคุณ ผู้ใช้จะพบกับCold Start ที่ช้า แอปที่ลด การใช้หน่วยความจำเมื่อเข้าสู่เบื้องหลังมีแนวโน้มที่จะถูกปิดใน เบื้องหลังน้อยกว่า

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

Kotlin

class MainActivity : AppCompatActivity(), ComponentCallbacks2 {
    override fun onTrimMemory(level: Int) {
        if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
            // Release memory related to UI elements, such as bitmap caches.
        }
        if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
            // Release memory related to background processing, such as by
            // closing a database connection.
        }
    }
}

Java

public class MainActivity extends AppCompatActivity implements ComponentCallbacks2 {
    public void onTrimMemory(int level) {
        switch (level) {
            if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
                // Release memory related to UI elements, such as bitmap caches.
            }
            if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
                // Release memory related to background processing, such as by
                // closing a database connection.
            }
        }
    }
}

C#

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

class LowMemoryTrigger : MonoBehaviour
{
    private void Start()
    {
        Application.lowMemory += OnLowMemory;
    }
    private void OnLowMemory()
    {
        // Respond to low memory condition (e.g., Resources.UnloadUnusedAssets())
    }
}

ใช้หน่วยความจำอย่างประหยัด

จัดสรรหน่วยความจำอย่างรอบคอบเพื่อไม่ให้หน่วยความจำหมด รายการบางอย่างที่ควรพิจารณามีดังนี้

  • ขนาดของ RAM จริง: เกมมักจะใช้ RAM จริงในอุปกรณ์ประมาณ ¼ ถึง ½
  • ขนาด zRAM สูงสุด: zRAM ที่มากขึ้นหมายความว่าเกมอาจมีหน่วยความจำมากขึ้น ที่จะจัดสรร จำนวนนี้อาจแตกต่างกันไปตามอุปกรณ์ ให้มองหา SwapTotal ใน /proc/meminfo เพื่อค้นหาค่านี้
  • การใช้หน่วยความจำของระบบปฏิบัติการ: อุปกรณ์ที่กำหนด RAM ให้กับกระบวนการของระบบมากกว่าจะเหลือหน่วยความจำสำหรับเกมของคุณน้อยลง ระบบจะปิดกระบวนการของเกม ก่อนที่จะปิดกระบวนการของระบบ
  • การใช้หน่วยความจำของแอปที่ติดตั้ง: ทดสอบเกมในอุปกรณ์ที่มีการติดตั้งแอปจำนวนมาก แอปโซเชียลมีเดียและแอปแชทต้องทำงานอยู่ตลอดเวลาและส่งผลต่อ ปริมาณหน่วยความจำที่ว่าง

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

หลีกเลี่ยงการสลับหน้า

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

อาการอย่างหนึ่งของการเกิด Thrashing คือเวลาเฟรมที่นาน ซึ่งอาจนานถึง 1 วินาทีหรือมากกว่า โปรดลด ปริมาณหน่วยความจำของเกมเพื่อแก้ไขปัญหานี้

ใช้เครื่องมือที่มี

Android มีชุดเครื่องมือที่จะช่วยให้เข้าใจวิธีที่ระบบ จัดการหน่วยความจำ

Meminfo

เครื่องมือนี้จะรวบรวมสถิติหน่วยความจำเพื่อแสดงปริมาณ หน่วยความจำ PSS ที่จัดสรรและหมวดหมู่ที่ใช้

พิมพ์สถิติ meminfo โดยใช้วิธีใดวิธีหนึ่งต่อไปนี้

  • ใช้คำสั่ง adb shell dumpsys meminfo package-name
  • ใช้การเรียก MemoryInfo จาก Android Debug API

สถิติ PrivateDirty แสดง ปริมาณ RAM ภายในกระบวนการที่ย้ายไปยังดิสก์ไม่ได้และไม่ได้แชร์ กับกระบวนการอื่นๆ ระบบจะใช้หน่วยความจำส่วนใหญ่ได้เมื่อปิดกระบวนการดังกล่าว

จุดติดตามหน่วยความจำ

Tracepoint ของหน่วยความจำจะติดตามปริมาณ หน่วยความจำ RSS ที่เกมของคุณใช้ การคำนวณการใช้งานหน่วยความจำ RSS เร็วกว่าการคำนวณการใช้งาน PSS มาก เนื่องจากคำนวณได้เร็วกว่า RSS จึงแสดงรายละเอียดที่ละเอียดยิ่งขึ้นเกี่ยวกับการเปลี่ยนแปลงขนาดหน่วยความจำเพื่อให้วัดการใช้งานหน่วยความจำสูงสุดได้แม่นยำยิ่งขึ้น ดังนั้น คุณจึงสังเกตเห็นจุดสูงสุดที่อาจทำให้เกมใช้หน่วยความจำจนหมดได้ง่ายขึ้น

Perfetto และการติดตามแบบยาว

Perfetto คือชุดเครื่องมือสำหรับรวบรวมข้อมูลประสิทธิภาพและหน่วยความจำในอุปกรณ์ แล้วแสดงใน UI บนเว็บ โดยรองรับการติดตามที่ยาวนานตามต้องการเพื่อให้คุณดูการเปลี่ยนแปลงของ RSS เมื่อเวลาผ่านไปได้ นอกจากนี้ คุณยังออกคำค้นหา SQL ในข้อมูลที่สร้างขึ้นเพื่อการประมวลผลแบบออฟไลน์ได้ด้วย เปิดใช้การติดตามแบบยาวจากแอปการติดตามระบบ ตรวจสอบว่าได้เปิดใช้หมวดหมู่memory:Memory สำหรับการติดตามแล้ว

heapprofd

heapprofd เป็นเครื่องมือติดตามหน่วยความจำ ซึ่งเป็นส่วนหนึ่งของ Perfetto เครื่องมือนี้ช่วยคุณค้นหาหน่วยความจำรั่วได้โดยแสดงตำแหน่งที่จัดสรรหน่วยความจำโดยใช้ malloc heapprofd สามารถเริ่มต้นได้โดยใช้สคริปต์ Python และเนื่องจากเครื่องมือนี้มีค่าใช้จ่ายต่ำ จึงไม่ส่งผลต่อ ประสิทธิภาพเหมือนเครื่องมืออื่นๆ เช่น Malloc Debug

รายงานข้อบกพร่อง

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

ดูข้อมูลเพิ่มเติมได้ที่ บันทึกและอ่านรายงานข้อบกพร่อง