【问题标题】:Weird performance issue with Galaxy TabGalaxy Tab 出现奇怪的性能问题
【发布时间】:2011-07-18 01:50:14
【问题描述】:

我正在编写 2d 教程,并且能够在三星 Galaxy Tab 上测试我当前的教程部分。

本教程只是在屏幕上随机移动默认图标。轻按一下,我创建了一个新的移动图标。只要屏幕上有 25 个或更少的元素,Galaxy 上的一切都可以正常工作(恒定为 60fps)。

使用第 26 个元素,帧速率降至 25fps。

当我将图像的大小/尺寸更改为更大的图像时,我在第 26 个元素之前达到不到 25fps。没关系。但是在某些不可重现的元素数量上,帧从(大部分超过)10fps 下降到 1fps。

在我的 Nexus One 上,我可以添加 150 个元素,但仍然有 50fps。

我所做的:我将位图变量更改为静态变量,因此并非每个元素都有自己的图像,但都使用相同的图像。这消除了这种行为,但我怀疑这个解决方案是一个好的解决方案。神奇的数字 25 表明我只能以这种方式使用 25 个不同的图像。

有人知道什么会导致这种行为吗?是三星修改安卓版的bug吗?

我的sample eclipse project is available。如果三星用户能用样品检查他们的性能,我将不胜感激。

编辑

一位同事找到了解决方案。他改变了位图的加载方式

mBitmap = BitmapFactory.decodeResource(res, R.drawable.icon);

mBitmap = BitmapFactory.decodeStream(new BufferedInputStream(res.openRawResource(R.drawable.icon)));

但我们仍然不明白为什么它会这样工作......

【问题讨论】:

  • 刚刚在我的 Galaxy Tab 上尝试过,帧率似乎与你的匹配。
  • 在我的 Nexus S 上,它在大约 210 个元素时下降到 50fps

标签: android performance surfaceview galaxy-tab


【解决方案1】:

我已经在 HTC Desire HD 上尝试了您的代码,并且在使用 Android 2.2 目标添加第 20 张图像后,帧速率下降到无法使用。当我导出与 android 2.1 版相同的代码时,它运行良好,可以处理 200 多个实例! 我怀疑这与在 2.2 上创建 GraphicObject 类的实例有关,但不太确定...

【讨论】:

  • 感谢测试。问题是为什么。该类并不复杂,位图有 4kb 和 72pixel 尺寸(hdpi 版本)。我将尝试在工作中在不同的设备上测试样本。感谢您的反馈!
  • 请注意,我使用的是相同的设备,只是更改了目标操作系统。
  • 标签有 2.2,我的项目目标是 2.1。将其更改为 2.2(以及 minSdkVersion)并没有改变任何内容。
  • 有些奇怪,因为它在 HTC Desire HD (2.2) 上运行良好,当作为针对 2.1 的项目安装时。抱歉,我无法提供更多帮助。
【解决方案2】:

嗯,我一直在查看您的项目,一切似乎都很好,但我知道是什么导致您的帧速率下降。

你在运行时分配对象。如果你不这样做,它会让你在开始时创建所有对象,因此你应该直接注意到显着下降(如果我的解决方案没有'不解决你的问题)。

这就是说; 我不确定对象池是否能解决你的问题,但你可以试试。在构造函数中初始化您的对象,而不是在 onTouchEvent(): 中进行此调用

new Element(getResources(), (int) event.getX(), (int) event.getY())

您应该有类似mElement.add(objectPool.allocate()) 的内容,其中对象池会在池中找到未使用的对象。此外,我们应该在该对象池中有指定数量的对象,然后您可以从那里检查是导致此错误的分配还是其他原因。

使用第 26 个元素,帧速率降至 25fps。

当(或者如果)你实现了这个,你应该直接看到帧率下降(如果这不能解决你的问题),因为对象池会让你分配一个固定的数量(例如,也许 100 个元素?)在开始时(但你没有在视觉上使用它们)。

另外,我在我的一个 Android 示例应用程序中使用了内存池模式(对象池)。在那个样本中;我使用对象池向onTouchEvent() 上的Canvas 添加一行(在运行时不分配)。在该源代码中,您可以轻松更改对象的总数并检查并自己尝试。如果您想查看我的示例应用程序(和源代码),请写下评论,我很乐意分享它,因为它尚未公开。我的 cmets 是 瑞典语,但我认为你应该能够理解,因为变量和方法是 英语。 :)

旁注:您写道,您已经尝试(甚至成功)通过设置Bitmap static 来消除该行为。就像现在一样,您的元素具有Bitmap 的不同实例,这将使您在每次构造新对象时分配一个新的Bitmap。这意味着每个对象在使用相同资源时都指向不同的Bitmapstatic 是一个完全有效的解决方案(尽管 25 的幻数似乎很奇怪)。

这个Bitmap 案例可以与OpenGL 系统进行比较。如果您有 20 个对象都应该使用相同的资源,则有两种可能的解决方案:它们可以指向相同的 VRAM 纹理,或者它们可以指向不同的 VRAM 纹理(就像您不使用 static 时的情况一样),但仍然是相同的资源。

编辑

Here is my sample application for Android 演示了内存池。

关于BitmapFactory 的解决方案,这可能取决于该类的工作方式。我不确定,但我认为decode...() 方法之一会生成一个新的Bitmap,即使它是相同的资源。 new BufferedInputStream(res.openRawResource(R.drawable.icon)) 可能会从内存中重用 BufferedInputStream,尽管这是一个很大的猜测。

您应该做的(在这种情况下)是解码资源并将来自它的引用存储在 Panel 类中,然后将该引用传递给 new Element(bitmapReference, ...)。这样,您只需分配一次,并且每个元素都指向内存中相同的Bitmap

【讨论】:

  • 如果你能分享你的示例代码,我真的很想看看。我用一个非常简单的对象池进行了尝试,我首先创建了 100 个元素,但只显示了其中的一些。随着每个触摸事件,显示元素的数量增加,即使加载了 100 个元素并显示了 25 个,我也得到了 60fps。到 26 日,25fps 的下降仍然存在。无论如何,一位同事找到了解决方案,作为编辑添加到我的答案中
  • @WarrenFaith:用我的项目链接更新了我的答案。我还添加了一些关于如何重用相同的 Bitmap 引用的信息,这样每次创建新元素时都不需要从 BitmapFactory 类返回新的 Bitmap
  • 谢谢分享。一般来说,我会创建一个位图缓存,在其中存储位图并与想要显示它的每个人共享同一个实例。我认为这通常是最好的解决方案。但这有点离题了,因为性能下降不应该这么快发生。不是 25 个元素……至少我不希望这样……
  • @WarrenFaith:没问题。你提到的解决方案可能是最好的。
【解决方案3】:

我相信我可以对这个问题有所了解。

至少在我的 Galaxy S 上,Gingerbread 2.3.5 第一个代码使用 Bitmap.Config = ARGB_8888 将我的 test.png 加载到 Bitmap 中,而第二个代码使用 Bitmap.Config = RGB565 加载。奇怪的是,虽然 Gingerbread 默认应该创建 32 位表面,但 RGB565 的“渲染”(我分析并比较了对 drawBitmap 的原生调用)要快得多。

因此,第二个想法,更适合您的整个示例,是 ARGB888 位图确实具有 alpha,因此在这种情况下,渲染 25 个以上精灵的重叠图像可能会在 alpha 计算算法中产生一些瓶颈,而 RGB565 图像会很好而且很快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多