2011-01-11 221 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的任何紋理都被複制到一個單獨的內存區域。這可能在圖形硬件本身上,或者作爲內核空間內核視頻驅動程序的一部分。無論哪種方式,使用的紋理內存都不會反映在您的應用程序中。

希望有所幫助。