安卓图形大量消耗堆内存?-LibGDX

8
我现在有一个空的LibGDX应用程序,什么也没有做。它不渲染任何内容,也不更新任何内容。它只是一个空白的屏幕。当我将应用程序部署到Android设备时,会出现可怕的内存消耗。在我的设备上运行应用程序时,使用DDMS创建以下堆转储: 最重要的内存使用是13.163 MB的1字节数组分配。这不是堆的一半吗?! 检查分配情况,发现没有分配那个大小的内容。 现在使用Eclipse MAT分析堆转储: 所以,在字节数组中高内存使用仍然来自安卓图形。我甚至没有画任何东西!是否有任何方法可以避免安卓图形部分占用堆的一半。这只会导致在实际发生事情时产生过多的垃圾回收,或者这很正常,我必须处理它吗? 注意:我正在三星Galaxy S4上运行此应用程序,使用libGDX版本1.4(或最新版本)。 更新:我已经发现14-13MB字节数组分配对于应用程序来说是正常的,但我仍然有问题。我的堆大小太小了。如果安卓图形占据了我的堆的一半,我就没有多余的空间用于有用的东西,垃圾回收器就会发狂。对于我使用旧版本libgdx创建的另一个应用程序(无可否认地编写得更差),堆大小为73 Mb。如何增加堆大小?我认为73 Mb相当大,您可以看到大部分都没有使用。以下是旧应用程序的堆统计数据:

1
你尝试过分配一些垃圾来尝试超出具有小堆大小的第一个应用程序的堆大小吗?如果没有,请尝试一下。这样做时,它是否会自动增加其堆大小? - Seyf
3个回答

6
在Android 2.3版本之后,除了使用android:largeHeap属性外,您无法对堆的大小做任何处理。
如果您想要一个大堆而不管怎样有两种方法可以作弊:
1.使用本地API分配内存:这不是个好主意,因为它会增加复杂性,如果您没有计划在本地代码中执行操作,则不需要此方法; 2.在您的执行之前分配一个不必要的大对象以获取所需的堆空间:虽然它可能会给您足够的堆空间,但不能保证堆大小不变。
然而,如果需要时重新调整堆的初始大小并不是问题。我的游戏生命周期中的内存管理观点与上述两种方式和您当前的做法略有不同。
对于关卡或阶段等,您不应在需要时精确分配内存。这不仅会引起内存分配时的停顿,还可能因为可能的存储I/O而造成停顿。任何事物,如声音、图形、字体等,都应在关卡之前准备好。这就是为什么很多游戏都有“加载”屏幕。您应该在开始玩之前准备好所有可以做的事情。
对于小型关卡,这样做没问题-但仍然不好。随着事情的变得复杂,性能会下降。许多游戏(如体育游戏、赛车游戏等)在开始游戏之前进行分配。其他游戏尽可能地进行分配。一些开放世界游戏(如GTA)不会加载地图中的所有地图对象,但它们具有绘制距离,因此它们随着您在地图中移动而绘制,并在内存没有足够空间时从内存中删除最远的对象。
[您的旧版LibGDX应用程序获得更大的堆大小的原因可能是分配导致堆大小增加并释放了一些堆来使得您获得了良好的30%使用率。]

谢谢,这非常有帮助! - Matthew Tory

1
你可以在Android清单文件中分配此属性的值: < p > android:largeHeap="true" < /p > 注意,这仅适用于Android 3.0+版本。

将此添加到清单后,堆大小仍保持在26.465Mb,远远达不到另一个应用程序的73.855Mb。我最近发现,只有在内存不足时才会调整堆大小,而我并没有遇到这种情况。应用程序卡顿仍经常发生,导致GC_FOR_ALLOC,我希望通过增加堆大小来减少这种情况?在我提到的第二个应用程序中,只使用了30%,这意味着GC_FOR_ALLOC不会经常发生。在第一个应用程序中使用了60%。 - Matthew Tory
有没有办法扩大堆大小,即使我在技术上并不需要它? - Matthew Tory
我很抱歉,我不知道其他的方法。我知道的唯一方式就是上面提到的。 - Bowersbros

1

你可以找到分配的对象如何与其他对象连接,并通过这种方式找到内存泄漏。 https://developer.android.com/tools/debugging/debugging-memory.html 使用Eclipse Memory Analyzer工具 - konmik
我最近将这个回答标记为“不是答案”,但是标记被拒绝了。它似乎是有效的内容,但缺乏一个伟大答案的上下文。你可能想要扩展它以增加清晰度? - brandonscript
我不理解你所说的“回答-非回答-有效”想法。但是,如果你只是想了解更多细节,你可以观看这个视频:http://www.youtube.com/watch?v=_CruQY55HOk - konmik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接