2011-01-11 169 views
2

我试图优化我的原生Android应用程序中的纹理内存消耗。我有两个计数器:第一是我自己的那递增称为每次TexImage:OpenGL ES纹理内存

g_cbTextureMemory += ImageLineBytes(Format, width) * height; 

你可以假设TexImage纹理调用一次,在我真正的代码中有当前的影像尺寸的递减不是增加新的,如果质地重新分配,但实际重新分配不会发生。

二是从系统:

adb shell dumpsys meminfo my.app.name 

它给这样的事情:

** MEMINFO in pid 3269 [my.app.name] ** 
        native dalvik other total 
      size: 39320[*] 6663  N/A 45983 
     allocated: 21453  3945  N/A 25398 
      free:  34  2718  N/A  2752 
      (Pss):  6281  3078 40643 50002 
    (shared dirty):  2240  4968 12108 19316 
    (priv dirty):  6232  2684 17948 26864 

之后,我做到以下几点:我更换所有纹理使用1x1(通过发送假的1x1图像到glTexImage)。我看到meminfo给出了另一个结果,不同的单元格[22]在22Mb上发生了变化。但我的柜台显示我有25Mb的纹理,所以我期望25Mb。

那么在转储纹理内存消耗隐藏的地方呢?要清楚,对于1x1纹理转储是:

** MEMINFO in pid 3269 [my.app.name] ** 
        native dalvik other total 
      size: 16892  5575  N/A 22467 
     allocated: 13211  3574  N/A 16785 
      free:  208  2001  N/A  2209 
      (Pss):  6273  3122 17016 26411 
    (shared dirty):  2252  5032 10756 18040 
    (priv dirty):  6224  2588  5848 14660 

为什么我没有得到25Mb?是统计错误?本地堆是否包含纹理内存(看起来是这样)?或者,也许对于某些格式,Android的内部格式与我发送的格式不同?例如,R8G8B8转变为更优化的东西(看起来不是)?可能一切都好,有合理的解释吗?

回答

2

这里有几个问题。

我假设你通过比较'大小'行来得到22MB的差异。这是进程总共请求的内存量。有两个因素可以促成这个价值。

首先,有可能(也可能)该区域中的许多虚拟页面尚未分配给物理内存。物理分配仅在流程实际引用先前未使用的虚拟页面时发生。在这种情况下,MMU使CPU陷入内核,然后内核找到并分配一个物理页面来支持虚拟页面。因此,即使在没有交换空间的便携式Android设备上,只要大多数页面都未被引用,进程的可用空间就有可能远远超过可用的物理RAM。

影响进程大小的第二个因素是C库(或Dalvik VM或任何用户空间内存管理)将以比应用程序所请求的更大的块的形式请求内存。这是出于性能原因而完成的,因为经常分配/取消分配小缓冲区可以在不进行系统调用的情况下完成。因此,一个进程使用的实际内存不能很好地用上面的size参数表示 - 它只能用作一个粗略的上限。事实上,'已分配'行将更好地指示应用程序使用的最大内存,因为它跟踪实际引用的页面。

无论如何,据我所知,通过glTexImage发送给OpenGL的任何纹理都被复制到一个单独的内存区域。这可能在图形硬件本身上,或者作为内核空间内核视频驱动程序的一部分。无论哪种方式,使用的纹理内存都不会反映在您的应用程序中。

希望有所帮助。