有效管理遊戲中的記憶體

在 Android 平台上,系統會嘗試盡可能使用系統記憶體 (RAM),並視情況執行各種記憶體最佳化作業,以釋出空間。這些最佳化作業可能會對您的遊戲造成負面影響,不是使遊戲速度變慢,就是使遊戲完全終止。如要進一步瞭解這些最佳化作業,請參閱「程序之間的記憶體配置」這個主題。

本頁面說明可以採取哪些步驟,來避免記憶體不足導致遊戲受到影響的情況。

回應 onTrimMemory()

系統使用 onTrimMemory()敬上 通知應用程式生命週期事件, 自行降低記憶體用量,避免 低記憶體終止工具 (LMK) 釋出記憶體供其他應用程式使用

如果應用程式在背景終止,則使用者下次啟動時。 就會導致 冷啟動。這類應用程式可減少 查看背景記憶體時 背景。

回應剪輯事件時,最好釋出大量記憶體配置 不需要立即重建,而且可以視需要重建。適用對象 例如,如果應用程式具有從本機解碼的點陣圖快取 嘗試修剪或清除這個檔案 快取 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())
    }
}

使用 Memory Advice API Beta 版

Memory Advice API 是以 onTrimMemory 則比其他類型更高的喚回度和精確度 預測即將發生的 LMKAPI 會預估 應用程式會在某些情況下通知應用程式 超過門檻API 也能回報 記憶體用量Memory Advice API 可做為 onTrimMemory敬上 以便管理記憶體

如要使用 Memory Advice API,請參閱入門指南

對記憶體預算持保守態度

保守地分配記憶體預算,以免記憶體耗盡。以下列出一些需要注意的事項:

  • 實體 RAM 大小:遊戲通常使用裝置上 ¼ 到 ½ 之間的實體 RAM 容量。
  • zRAM 大小上限:如果 zRAM 容量較大,表示遊戲可能有更多記憶體可以分配。實際容量可能因裝置而異;在 /proc/meminfo 中尋找 SwapTotal,以找出這個值。
  • OS 的記憶體用量:為系統程序指定較多 RAM 的裝置,留給遊戲較少記憶體。在終止系統程序前,系統會先終止遊戲程序。
  • 安裝版應用程式的記憶體用量:在已安裝多個應用程式的裝置上測試遊戲。社群媒體和即時通訊應用程式必須持續執行,且會影響免費記憶體容量。

如果無法承諾以保守方式使用記憶體預算,請採取更為彈性的方法。如果系統碰到記憶體不足的問題,請減少遊戲使用的記憶體容量。例如,分配較低解析度的紋理或儲存較少著色器來回應 onTrimMemory()。尤其在遊戲設計階段,這種動態分配記憶體配置的方式會增加開發人員的工作量。

避免輾轉現象

當免費記憶體偏低,但不至於導致遊戲終止時,就會發生「輾轉現象」。在這種情況下,kswapd 會收回遊戲所需的網頁,因此會嘗試從記憶體中重新載入網頁。空間不足,因此網頁會不斷替換 (連續替換)。 系統追蹤功能會將這個情形回報為 kswapd 持續執行的執行緒。

輾轉現象其中一個徵兆為影格時間較長,可能是一秒鐘或是更長。如要解決這個問題,請減少遊戲的記憶體用量。

使用可用的工具

Android 提供一系列工具,可協助您瞭解系統管理記憶體的方式。

Meminfo

這項工具會收集記憶體統計資料,以顯示 PSS 記憶體的分配情形,以及所使用的記憶體類別。

請以下列其中一種方式列印 meminfo 統計資料:

  • 使用 adb shell dumpsys meminfo package-name 指令:
  • 使用 Android Debug API 的 MemoryInfo 呼叫。

PrivateDirty 統計資料會顯示程序中無法分頁至磁碟,且不會與任何其他程序共用的 RAM 容量。當相應的程序終止時,大部分的用量會開放給系統使用。

記憶體追蹤點

記憶體追蹤點會追蹤遊戲使用的 RSS 記憶體量。計算記憶體用量的速度比計算 PSS 用量來得快。RSS 可更快速地進行計算,因此能更精細地分析記憶體大小的變化,以更準確地測量尖峰記憶體用量。 因此,您會更容易注意到造成遊戲記憶體不足的尖峰用量。

Perfetto 與長期追蹤記錄

Perfetto 是一套工具,用於收集裝置上的效能和記憶體資訊,並將其顯示在網頁式的使用者介面中。這項工具支援任意長度的追蹤記錄,因此您可以查看 RSS 隨著時間的變化情形。 也可以針對這項工具產生的資料執行 SQL 查詢,以進行離線處理。請透過系統追蹤應用程式啟用長期追蹤記錄,並確認已啟用追蹤記錄的 memory:Memory 類別。

heapprofd

heapprofd 是 Perfetto 中的一種記憶體追蹤工具。這項工具使用 malloc 顯示記憶體分配位置,可協助發現記憶體流失的情況。heapprofd 可以使用 Python 指令碼啟動,而且由於這項工具造成的負擔較低,因此不像 Malloc Debug 等其他工具會影響效能。

bugreport

bugreport 是一款記錄工具,可協助您瞭解遊戲是否因記憶體不足而當機。相較於 Logcat,這項工具的輸出內容更為詳細。這對於記憶體偵錯很有幫助,因為這項工具會顯示遊戲是否因記憶體不足而當機,或是因 LMK 而終止。

詳情請參閱擷取和讀取錯誤報告一文。