Galaxy Tab 出现奇怪的性能问题
我正在编写 2d 教程,并且能够在 Samsung Galaxy Tab 上测试我当前的教程部分。
本教程只是在屏幕上随机移动默认图标。通过点击,我创建了一个新的移动图标。只要屏幕上有 25 个或更少的元素,Galaxy 上的一切都可以正常运行(始终为 60 fps)。
第 26 个元素的帧速率降至 25fps。
当我将图像的大小/尺寸更改为更大的图像时,在第 26 个元素之前我达到了不到 25fps。没关系。但在某些无法真正重现的元素数量处,帧从(大部分超过)10fps 下降到 1fps。
在我的 Nexus One 上,我可以添加 150 个元素,并且仍然具有 50fps。
我所做的:我将位图变量更改为静态变量,因此并非每个元素都有自己的图像,但都使用相同的图像。这消除了这种行为,但我怀疑这个解决方案是不是一个好的解决方案。神奇的数字 25 表明我只能以这种方式使用 25 个不同的图像。
有人知道什么会导致这种行为吗?难道是三星修改后的android版本的bug?
我的 示例 Eclipse 项目可用。如果一些三星用户能用样品检查他们的性能,我将不胜感激。
编辑
一位同事找到了解决方案。 的加载方式
mBitmap = BitmapFactory.decodeResource(res, R.drawable.icon);
他改变了位图
mBitmap = BitmapFactory.decodeStream(new BufferedInputStream(res.openRawResource(R.drawable.icon)));
,但我们仍然不明白为什么它会这样工作......
I am working on a 2d tutorial and was able to test my current tutorial part on a Samsung Galaxy Tab.
The tutorial simply moves the default icon randomly over the screen. With a tap I create a new moving icon. Everything works fine (constantly 60fps) on the Galaxy as long as I have 25 elements or less on the screen.
With the 26th element the frame rate drops to 25fps.
When I change the size/dimension of the image to a much bigger one, I reach less than 25fps before the 26th element. Thats ok. But at some not really reproducible number of elements the frame drops from (mostly more than) 10fps to 1fps.
On my Nexus One I can add 150 elements and still have 50fps.
What I have done: I changed the bitmap variable to a static one, so not every element has his own image but all use the same. That removed the behavior, but I doubt this solution is a good one. The magic number of 25 would suggest that I can use only 25 different images in that way.
Does someone have any idea what can cause this behavior? Is it a bug in the modified android version of Samsung?
My sample eclipse project is available. I would appreciate if some Samsung owner would check their performance with the sample.
edit
A colleague found a solution. He changed the way the bitmap is loaded from
mBitmap = BitmapFactory.decodeResource(res, R.drawable.icon);
to
mBitmap = BitmapFactory.decodeStream(new BufferedInputStream(res.openRawResource(R.drawable.icon)));
But we still don't really get it why it works this way...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
好吧,我一直在查看你的项目,一切似乎都很好,但我对导致帧速率下降的原因有一个想法。
你在运行时分配对象。如果你不这样做,它会让你在开始时创建所有对象,因此你应该直接注意到显着的下降(如果我的解决方案不能解决你的问题)。
也就是说; 我不确定对象池是否可以解决您的问题,但您可以尝试。在构造函数中初始化对象,而不是在
onTouchEvent()
中进行此调用:您应该有类似
mElement.add(objectPool.allocate())
的内容,其中对象pool 在池中找到未使用的对象。此外,我们应该在该对象池中拥有指定数量的对象,从那里您可以检查是否是分配导致了此错误,或者是否是其他原因。当(或如果)你实现这个时,你应该直接看到帧速率下降(如果这不能解决你的问题),因为对象池会让你在开始时分配固定数量(例如可能100个元素?)(但你并没有在视觉上使用它们)。
另外,我在 Android 示例应用程序之一中使用了内存池模式(对象池)。在该样本中;我使用对象池在
onTouchEvent()
上向Canvas
添加一行(无需在运行时分配)。在该源代码中,您可以轻松更改对象的总量并亲自检查并尝试。如果您想查看我的示例应用程序(和源代码),请写评论,我很乐意分享它,因为它尚未公开。我的评论是瑞典语,但我认为你应该能够理解,因为变量和方法是英语。 :)旁注:您写道,您已尝试(甚至成功)通过将您的
位图
设置为静态
来删除该行为。现在,您的元素具有不同的Bitmap
实例,这将使您在每次构造新对象时分配一个新的Bitmap
。这意味着当每个对象使用相同的资源时,它们都指向不同的位图。static
是一个完全有效的解决方案(尽管幻数 25 看起来很奇怪)。此
Bitmap
案例可以与OpenGL
系统进行比较。如果您有 20 个对象,它们都应使用相同的资源,则有两种可能的解决方案:它们可以指向相同的 VRAM 纹理,或者它们可以指向不同的 VRAM 纹理(就像您不使用时的情况一样) static
),但资源仍然相同。编辑:
这是我的示例用于演示内存池的 Android 应用程序。
关于您使用 BitmapFactory 的解决方案,这可能取决于该类的工作方式。我不确定,但我认为
decode...()
方法之一会生成一个新的Bitmap
,即使它是相同的资源。可能的情况是 new BufferedInputStream(res.openRawResource(R.drawable.icon)) 正在重用内存中的 BufferedInputStream,尽管这是一个很大的猜测。您应该做的(在这种情况下)是解码资源并将其引用存储在 Panel 类中,然后将该引用传递到
new Element(bitmapReference, ...)
中。这样,您只需分配一次,并且每个元素都指向内存中的同一个Bitmap
。Well, I've been looking on your project and everything seems to be fine, but I have one idea about what's causing you the frame rate drop.
You're allocating objects during runtime. If you don't do that, it will make you create all objects at start, and therefore you should notice a significant drop directly (if my solution doesn't solve your problem).
That said; I'm not sure whether an object pool will solve your problem, but you can try. Initialize your objects in a constructor and instead of making this call in
onTouchEvent():
You should have something like
mElement.add(objectPool.allocate())
, where the object pool finds an unused object in the pool. Also, we should have a specified amount of objects in that object pool and from there you can check if it is the allocating that is causing this error or if it is something else.When (or if) you implements this, you should see the frame rate drop directly (if this doesn't solve your problem though), since the object pool will make you allocating a fixed amount (e.g. maybe 100 elements?) at start (but you're not using them visually).
Also, I have used the memory pool pattern (object pool) in one of my sample applications for Android. In that sample; I add a line to the
Canvas
on anonTouchEvent()
using an object pool (without allocating during runtime). In that source code you can easily change the total amounts of objects and check it out and try it yourself. Write a comment if you want to look at my sample application (and source code) and I will gladly share it since it's not public yet. My comments are in Swedish, but I think you should be able to understand, since the variables and methods are in English. :)Side note: You wrote that you've tried (and even success) with removing the behaviour by making your
Bitmap
static
. As it is right now, your elements have different instances of aBitmap
, which will make you allocate a newBitmap
everytime you're constructing a new object. That means that every object is pointing to a differentBitmap
when they are using the same resource.static
is a fully valid solution (although a magic number of 25 seems wierd).This
Bitmap
case can be compared to theOpenGL
system. If you have 20 objects which all should use the same resource, there are two possible solutions: They can point to the same VRAM texture or either they can point to a different VRAM texture (like your case when you're not usingstatic
), but still same resource.EDIT:
Here is my sample application for Android that demonstrates the Memory Pool.
Regarding your solution with
BitmapFactory
, that probably depends on how that class works. I'm not sure, but I think that one of thedecode...()
methods generates a newBitmap
even if it is the same resource. It can be the case thatnew BufferedInputStream(res.openRawResource(R.drawable.icon))
is reusing theBufferedInputStream
from memory, although, that is a big guess.What you should do (in that case) is to decode a resource and store a reference from it in the Panel class and pass that reference into the
new Element(bitmapReference, ...)
instead. In that way, you're only allocating it once and every element is pointing to the sameBitmap
in memory.我已在 HTC Desire HD 上尝试过您的代码,在使用 Android 2.2 目标添加第 20 张图像后,帧速率下降至无法使用。当我导出与 android 版本 2.1 相同的代码时,它工作正常并且可以处理超过 200 个实例!
我怀疑这与在 2.2 上创建 GraphicObject 类的实例有关,但不太确定......
I have tried your code on HTC Desire HD and the frame rate drops down to unusable after added 20th image using Android 2.2 target. When I exported the same code as android version 2.1 then it worked fine and could handle over 200 instances!
I suspect that it is to do with creating instances of your GraphicObject class on 2.2, but not quite sure...
我相信我可以阐明这个问题。
至少在我的 Galaxy S 上,Gingerbread 2.3.5
第一个代码使用 Bitmap.Config = ARGB_8888 将我的 test.png 加载到位图中,而第二个代码使用 Bitmap.Config = RGB565 加载。奇怪的是,虽然 Gingerbread 默认情况下应该创建 32 位表面,但 RGB565“渲染”(我分析并比较了对 drawBitmap 的本机调用)要快得多。
因此,第二个想法,更适合您的整个示例,是 ARGB888 位图确实有 alpha,因此在这种情况下,渲染 25 个以上精灵的重叠图像可能会在 alpha 计算算法中产生一些瓶颈,而 RGB565 图像就可以了而且速度快。
I believe i can shed some light on this problem.
At least on my Galaxy S, Gingerbread 2.3.5
the first code loads my test.png into Bitmap with Bitmap.Config = ARGB_8888, while the second code loads with Bitmap.Config = RGB565. The strange thing is, while Gingerbread by default supposed to create 32bit surface, the RGB565 'renders' (I profiled and compared native call to drawBitmap) much faster.
Hence, The second idea, more appropriate for the your example as a whole, is that ARGB888 Bitmap does have alpha, so in that case rendering overlapping images of 25+ sprites could create some bottleneck in alpha calculation algorithm, while RGB565 image would be fine and fast.