OpenGL ES texture memory
I'm trying to optimize texture memory consumption in my native Android application. I have two counters: first is my own that incremented each time TexImage called:
g_cbTextureMemory += ImageLineBytes(Format, width) * height;
You may assume that TexImage called once for texture, in my real code there is decrement of current image size than adding new, if texture reallocated, but actually reallocations doesn't happen.
Second is from the system:
adb shell dumpsys meminfo my.app.name
It gives something like this:
** 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
After that I do the following: I replace all textures with 1x1 (by sending dummy 1x1 image to glTexImage). I see that meminfo gives another result and difference cell [*] changed on 22Mb. But my counter shows that I have 25Mb of textures, so I expect 25Mb.
So where in the dump texture memory consumption hidden? To be clear, for 1x1 textures dump is:
** 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
Why I didn't get 25Mb? Is is statistical error? Does native heap includes texture memory (seems that it is)? Or maybe for some formats Android have internal formats different from that I send? For example, R8G8B8 transformed to something more optimal (seems that it is not)? May it's all ok, and there is rational explanation?
There are a couple of issues here.
I assume that you get a 22MB difference by comparing the 'size' line. This is the amount of memory the process has requested in total. There are two factors that can contribute to this value.
For one, it's possible (and likely) that many of the virtual pages in that region have not been allocated to physical memory. A physical allocation only happens when a process actually references a previously unused virtual page. In that case, the MMU causes the CPU to trap into the kernel, which then finds and allocates a physical page to back the virtual one. So, it's possible that a process can have a size far in excess of the physical RAM available, even on a portable Android device without swap space, as long as most of those pages are never referenced.
A second factor that can influence the process' size is that the C library (or Dalvik VM, or any user-space memory management) will request memory in larger chunks than are requested by the application. This is done for performance reasons, since frequently allocating/deallocating small buffers can be done without making a system call. Therefore, the actual memory used by a process won't be well indicated by the size parameter above - it can only serve as a coarse upper bound. In fact, the 'allocated' line would be a better indication of the maximum memory in use by an application, since it tracks the pages actually referenced.
At any rate, as far as I understand it, any textures that you send to OpenGL via glTexImage are copied into a separate memory area. This may either be on the graphics hardware itself, or as part of the kernel video driver in kernel space. Either way, the texture memory used would not be reflected in your application.
Hope that helps.
精彩评论