Android opengles线程上的垃圾收集

Android opengles线程上的垃圾收集,android,opengl-es,garbage-collection,Android,Opengl Es,Garbage Collection,我的最后一个问题没有得到回答,所以我正在尝试一种不同的方法。我动态地将许多纹理(256x256 RGBA888)加载到内存中,并在需要时丢弃它们。问题是,有时当我将纹理上传到OpenGL时,它需要40-80毫秒,很少需要更多。我发现,这段缓慢的时间是在垃圾收集之后。问题是,此GC有时会阻止GL线程(FPS drop),有时会阻止纹理加载程序线程(OK)。有没有一种好方法可以不让GC发生在GL线程上 在每解码1、2、3…n个纹理后,我尝试在纹理加载器线程上调用System.gc(),这有效地删除了

我的最后一个问题没有得到回答,所以我正在尝试一种不同的方法。我动态地将许多纹理(256x256 RGBA888)加载到内存中,并在需要时丢弃它们。问题是,有时当我将纹理上传到OpenGL时,它需要40-80毫秒,很少需要更多。我发现,这段缓慢的时间是在垃圾收集之后。问题是,此
GC
有时会阻止
GL
线程(FPS drop),有时会阻止纹理加载程序线程(OK)。有没有一种好方法可以不让
GC
发生在
GL
线程上

在每解码1、2、3…n个纹理后,我尝试在纹理加载器线程上调用
System.gc()
,这有效地删除了
GL
线程上的
gc-ing
,但现在纹理加载要慢得多,因为该线程必须等待gc完成。将“n”变大会加快加载速度,但是
GL
线程上的
GC
更可能发生,因此动画会出现断断续续的情况

对于在不同线程中解码的位图,是否有某种方法可以删除
GL
线程上的
GC-ing
?我不会在
GL
线程上解码/分配任何位图,只有在加载新纹理时才会执行
GC压缩

编辑:
这款应用的目标用户是安卓3.2及更新版本的手机。这在手机(HTC One S-4.0.3)和平板电脑(Nexus 7-4.1,Galaxy Tab 2 10.1-3.2和4.0,Acer Icona A200-4.0)上都会发生。

您不能完全禁用垃圾收集,它将由Dalvik VM在没有您入侵的情况下启动

您可以通过使用一些自定义纹理加载来最小化内存分配和释放,例如使用预先分配的数组来存储源纹理数据等。正如您所提到的,所有纹理都具有相同的尺寸和颜色深度,因此对于任何图像,您都需要相同大小(256x256x4=262144字节)的临时缓冲区

最终,您可以将OpenGL代码移动到JNI C/C++代码中,以您想要的方式管理内存。

正因为如此,对于相同大小的磁贴和针对Android 3.0及更高版本的磁贴,有了一个简单的解决方案


这将为每个新的磁贴重复使用一个
位图
,因此不再使用furios GC。

您正在测试的android版本是什么?@Ali Imran编辑了我的帖子,添加了设备和Androodversions@Ali伊姆兰:这也是我很久以前的问题。它不会解决我当前的问题,因为每个BitmapFactory.decodeStream(…)将创建一个新位图,该位图将在将来某个时候进行GC解码。我在这个问题上使用了类似的方法,但没有“位图的双缓冲”,这最终没有给我带来任何优势。@Ali Imran,这也没有帮助:(我需要以某种方式将GC移动到另一个线程中,而不是暂停GL或位图加载程序线程。我正在考虑将位图创建部分移动到C中,但我还必须管理将位图发送到C中OpenGL的线程,因此java中没有位图实例,这将是GC-ed。您能告诉我如何发送java输入吗Stream(我从APK扩展文件中打开PNG)转换为本机代码,在那里解码并发送到GL线程,并在我的Java类instace“Tile”中设置纹理id和就绪标志?谢谢,我不擅长JNI编程,我建议你使用它,因为在本机C代码中,你可以用任何方式管理内存。或者,你可以用Java,但方式不同。不要将PNG文件加载到
Bitmap
中,而是以二进制RGBA888格式加载准备好的纹理,以便直接加载到GPU。这样你就可以你需要一个预先分配的临时缓冲区来加载你的所有纹理,请看我的编辑回答。在我的情况下,以8888格式解压它们不是最好的主意,这将是2GB左右的数据。我可能需要查看本机代码,混合Java和本机OpenGL ES调用。如果你不需要alpha,你可以使用ETC1压缩。Android 2.2及以上版本的所有设备都支持压缩。压缩也不适用于此应用,因为存在大量灰度图像和平滑渐变的图像。