在 Android 平台上,系统尝试使用尽可能多的系统内存 (RAM),并在需要时执行各种内存优化以释放空间。这些优化可能会对您的游戏产生负面影响,例如导致游戏速度变慢或完全崩溃。您可以在主题 进程间内存分配 中了解更多关于这些优化的信息。
本页面介绍了您可以采取的步骤,以避免低内存情况影响您的游戏。
响应 onTrimMemory()
系统使用 onTrimMemory()
通知您的应用内存不足,应用可能会被终止。许多情况下,这是您的应用收到的唯一警告。 相对于 低内存杀手 (LMK),此回调具有较高的延迟,因此快速响应回调至关重要。
响应此回调,减少分配的速度、数量和大小。 onTrimMemory()
传递一个常量来指示严重程度,但您应该响应第一个警告,因为可能分配速度比 onTrimMemory()
的反应速度快。
Kotlin
class MainActivity : AppCompatActivity(), ComponentCallbacks2 { override fun onTrimMemory(level: Int) { when (level) { ComponentCallbacks2.TRIM_MEMORY_MODERATE, ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW, ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL -> // Respond to low memory condition else -> Unit } } }
Java
public class MainActivity extends AppCompatActivity implements ComponentCallbacks2 { public void onTrimMemory(int level) { switch (level) { case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE: // Respond to low memory condition break; case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW: // Respond to low memory condition break; case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL: // Respond to low memory condition break; default: break;
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()) } }
使用内存建议 API beta
内存建议 API 是作为 onTrimMemory 的替代方案而开发的,它在预测即将到来的 LMK 方面具有更高的召回率和精度。该 API 通过估计正在使用的内存资源量来实现这一点,然后在超过特定阈值时通知应用。该 API 还可以将估计的内存使用率百分比直接报告给您的应用。您可以将内存建议 API 用作 onTrimMemory
事件的替代方案,用于内存管理。
要使用内存建议 API,请使用 入门指南。
保守使用内存预算
保守地预算内存,以避免内存不足。以下是一些需要考虑的因素:
- 物理 RAM 大小:游戏通常使用设备物理 RAM 量的一半到四分之一。
- 最大 zRAM 大小:zRAM 越多,游戏可分配的内存就越多。此数量根据设备而异;在
/proc/meminfo
中查找SwapTotal
以找到此值。 - 操作系统内存使用量:将更多 RAM 分配给系统进程的设备为您的游戏留下的内存更少。系统会在终止系统进程之前终止游戏的进程。
- 已安装应用的内存使用量:在安装了许多应用的设备上测试您的游戏。社交媒体和聊天应用需要持续运行,并且会影响可用内存量。
如果您不能保证保守的内存预算,请采用更灵活的方法。如果系统遇到低内存问题,请减少游戏使用的内存量。例如,响应 onTrimMemory()
分配分辨率较低的纹理或存储较少的着色器。这种动态的内存分配方法需要开发人员付出更多努力,尤其是在游戏设计阶段。
避免抖动
抖动是指当可用内存很低但不足以终止游戏时发生的情况。在这种情况下,kswapd
已回收游戏仍需使用的页面,因此它会尝试从内存中重新加载这些页面。没有足够的空间,因此这些页面会不断被换出(连续换出)。系统跟踪 将此情况报告为一个线程,其中 kswapd
持续运行。
抖动的一个症状是帧时间过长,可能是一秒或更长。减少游戏的内存占用量以解决此问题。
使用可用工具
Android 提供了一组工具,可帮助您了解系统如何管理内存。
Meminfo
此工具收集内存统计信息,以显示分配了多少 PSS 内存 以及用于这些内存的类别。
以下列出打印 meminfo 统计信息的方法:
- 使用命令
adb shell dumpsys meminfo package-name
。 - 使用 Android 调试 API 中的
MemoryInfo
调用。
PrivateDirty
统计信息显示进程内无法分页到磁盘且未与任何其他进程共享的 RAM 量。当该进程被终止时,这部分内存的大部分将可供系统使用。
内存跟踪点
内存跟踪点跟踪游戏使用的 RSS 内存 量。计算 RSS 内存使用量比计算 PSS 使用量快得多。由于计算速度更快,RSS 显示内存大小变化的更精细粒度,从而更准确地测量峰值内存使用量。因此,更容易注意到可能导致游戏内存不足的峰值。
Perfetto 和长跟踪
Perfetto 是一套工具,用于收集设备上的性能和内存信息,并将其显示在基于 Web 的 UI 中。它支持任意长的跟踪,因此您可以查看 RSS 如何随时间变化。您还可以对它生成的数据发出 SQL 查询,以便离线处理。从 系统跟踪应用 中启用长跟踪。确保为跟踪启用了 **memory:Memory** 类别。
heapprofd
heapprofd
是 Perfetto 的一部分,是一种内存跟踪工具。此工具可以通过显示使用 malloc
分配内存的位置来帮助您查找内存泄漏。可以使用 Python 脚本启动 heapprofd
,并且由于该工具的开销很低,因此不会像 Malloc Debug 等其他工具那样影响性能。
bugreport
bugreport
是一个日志记录工具,用于确定游戏是否因内存不足而崩溃。该工具的输出比使用 logcat 更详细。它对内存调试很有用,因为它会显示游戏是否因内存不足而崩溃,或者是被 LMK 终止的。
有关更多信息,请参阅 捕获和阅读错误报告。