【问题标题】:Android graphics huge heap memory consumption? - LibGDXAndroid显卡堆内存消耗巨大? - LibGDX
【发布时间】:2014-12-25 16:38:11
【问题描述】:

我目前有一个空白的LibGDX 应用程序,它什么都不做。它不渲染任何东西,也不更新任何东西。它只是一个空的Screen。当我将应用程序部署到 android 时,我会遇到一些可怕的内存消耗。当应用程序在我的设备上运行时,我使用 DDMS 创建了以下堆转储:

内存最重要的用途是 13.163 MB 的 1 字节数组分配。这不是堆的一半吗?!

我检查了分配,发现没有任何东西指向那个大小的分配:

现在我使用 Eclipse MAT 分析堆转储:

因此,内存的高使用率仍然来自 byte[] 数组。 进一步分析 byte[] 部分,我想出了这个:

我现在看到巨大的 byte[] 分配来自 android 图形。我什至什么都不会画!有什么办法可以避免这个应用程序的 android 图形部分占用一半的堆。这只会导致在事情实际发生时发生过多的垃圾收集,或者这是正常的,我只需要处理它?

注意:我在带有 libGDX 1.4 版(或任何最新版本)的三星 Galaxy S4 上运行它

更新:我没有发现 14-13MB 字节数组分配对于应用程序来说是正常的,但我仍然有问题。我的堆大小太小。如果 android 图形占据了我堆的一半,我就没有什么空间可以容纳任何有用的东西了,垃圾收集器就会发疯。在另一个应用程序上,我使用旧版本的 libgdx(不可否认的编码更差的应用程序)创建了另一个应用程序,堆大小为 73 Mb。如何增加堆大小?我认为 73 Mb 相当大,正如您所见,其中大部分都没有使用。以下是旧应用程序的堆统计信息:

【问题讨论】:

  • 您是否尝试分配一些垃圾来尝试超过第一个堆大小较小的应用程序的堆大小?如果没有,请这样做。完成后它会自动增加堆大小吗?

标签: java android memory libgdx heap-memory


【解决方案1】:

在 Android 2.3 之后,除了使用 android:largeHeap 属性之外,你无法对堆的大小做任何事情。

有两种方法可以欺骗如果你无论如何都想要一大堆:

  1. 使用本机 api 分配内存:这不是一个好主意,因为它会增加复杂性,并且如果您不打算使用本机代码执行操作,
  2. 在执行之前分配一个不必要的大对象以获得所需的堆空间:虽然它会给你一次足够的堆空间,但不能保证堆大小会保持不变。

但是,如果在需要时调整初始堆大小,则它不是问题。我对游戏生命周期中内存管理的看法与上面列出的两件事以及您可能正在做的事情有点不同。

对于关卡或阶段等,您不应在需要的确切时间分配内存。这不仅会在分配内存时造成卡顿,还会因为可能的存储 I/O 而卡顿。任何东西,比如声音、图形、字体等都应该在关卡之前准备好。这就是为什么很多游戏都有“加载”屏幕的原因。在开始游戏之前,您应该准备好任何可以做的事情。

对于一个小舞台,这样做是可以的-但仍然不好-。随着事情变得复杂,它会降低性能。很多游戏(如体育游戏、赛车游戏等)在开始游戏之前都会进行分配。其他人尽其所能做到这一点。一些开放世界游戏(如 GTA)不会加载地图中的所有地图对象,但它们具有绘制距离,因此它们会在您在地图中移动时绘制,并且当内存没有更多空间时它们会从内存中删除最远的对象.

[使用旧 LibGDX 版本的应用程序获得更多堆大小的原因可能是导致堆大小增加的分配和释放一些堆的释放,以便获得 30% 的良好使用率。]

【讨论】:

  • 谢谢,这很有帮助!
【解决方案2】:

您可以在 Android Manifest 中分配此属性值:

android:largeHeap="true"

注意,这仅适用于 Android 3.0+

【讨论】:

  • 将其添加到清单后,堆大小仍保持在 26.465Mb,与其他应用程序的 73.855Mb 相差甚远。我最近发现,只有在内存不足的情况下,如果该值为真,堆才会调整大小,而我不是。由 GC_FOR_ALLOC 引起的应用程序卡顿仍然经常发生,我希望可以通过增加堆大小来减少?在我提到的第二个应用程序中,只使用了 30%,这意味着 GC_FOR_ALLOC 不会经常发生。在第一个应用程序中,使用了 60%。
  • 有没有办法扩大堆大小,即使我在技术上不需要它?
  • 恐怕我不知道。我知道的唯一方法是上面的。
【解决方案3】:

在分配的对象上右键,选择“trace to GC root”,“排除弱引用”

http://www.youtube.com/watch?v=_CruQY55HOk

【讨论】:

  • 您可以通过这种方式找到分配的对象与其他对象的连接方式并找到内存泄漏。 developer.android.com/tools/debugging/debugging-memory.html 使用 Eclipse 内存分析器工具
  • 我最近将此答案标记为不是答案,但该标记被拒绝。它似乎是有效的内容,但缺乏一个很好的答案的上下文。为了清楚起见,您可能想扩展它?
  • 我不明白你的“回答不回答有效”的想法。但是,如果您只是想了解更多详细信息,可以观看此视频:youtube.com/watch?v=_CruQY55HOk
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-29
  • 2018-07-03
  • 2015-11-25
  • 2020-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多