在 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()) } }
使用内存建议 API 测试版
内存建议 API是作为 onTrimMemory 的替代方案开发的,它在预测即将到来的 LMK 方面具有更高的召回率和精度。该 API 通过估算正在使用的内存资源量,然后在超过特定阈值时通知应用来实现这一点。该 API 还可以将估计的内存使用百分比直接报告给您的应用。您可以使用内存建议 API 作为onTrimMemory
事件的替代方案来进行内存管理。
要使用内存建议 API,请使用入门指南。
保守使用内存预算
保守地预算内存以避免内存不足。需要考虑的一些项目包括:
- 物理 RAM 大小:游戏通常使用设备上物理 RAM 量的一半到四分之一。
- 最大 zRAM 大小:更多的 zRAM 意味着游戏可能有更多可分配的内存。此数量因设备而异;查找
SwapTotal
in/proc/meminfo
以查找此值。 - 操作系统的内存使用情况:将更多 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
Perfetto 内含的内存跟踪工具 heapprofd
可以帮助您查找内存泄漏,它会显示使用 malloc
分配内存的位置。heapprofd
可以使用 Python 脚本来启动,并且由于该工具开销低,因此不会像 Malloc Debug 等其他工具那样影响性能。
bugreport
bugreport
是一款日志工具,用于查找游戏崩溃是否由于内存不足导致。与使用 logcat 相比,该工具的输出更加详细。它对于内存调试非常有用,因为它可以显示游戏崩溃是因为内存不足还是被 LMK 终止。
更多信息,请参阅 捕获和阅读错误报告。