cocos2d-x與ISO內存管理


備註:圖片紋理加載所佔用的內存 = 長*寬*4,  圖片使用 RGBA 模式, 一個像素點,佔 4個字節

IOS設備的內存限制情況

設備                                              建議內存                   最大內存

iPad2/iPhone4s/iphone4                170-180mb                 512mb

iPad/iPod touch3,4/iphone3gs          40-80mb                  256mb

iPod touch1,2/iPhone3g/iPhone1         25mb                    128mb




1.慎用大圖片 
圖片佔用內存大小的算法爲一張1024*1024的圖片,加載成紋理後,佔用1024*1024*4(4m)內存。渲染成精靈後,又會佔用和紋理一樣的內存,所以這種圖片佔用的總內存是8m。(繪製精靈的時候,以精靈的繪製這種圖片的大小計算內存,例如只繪畫這張圖片的 某個 28*28大小的 區域, 那麼只需要一個 32 * 32 *4 = 4K的內存大小) 

2.圖片尺寸很重要 
圖片尺寸裏有大陷阱,1024*1024和1025*1025的圖片看似差不多,其實內存佔用有天壤之別,因爲cocos2d對圖片的尺寸是按2的N次方自適應的,所以1025*1025的圖片加載後實際紋理大小爲2048*2048,紋理將佔用8m內存!是1024*1024那張圖片的2倍。所以遇到類似尺寸圖片,最好先用PS調整下大小。 
  
3.使用工具查看內存佔用 
用xcode自帶的Leaks工具可以很方便的查看程序佔用的情況和尋找內存泄露的堆棧。 
  
4.檢查對象有沒被釋放 
當代碼越來越複雜的時候,你就要擔心某些對象可能在其他你沒注意的地方給保留了引用計數,導致你在對這個對象使用release方法時,實際對象並沒有被dealloc掉。所以你得通過在每個對象的dealloc方法中打上斷點調試或者輸出日誌,來確認該對象是否真的被釋放了。 
  
5.使用真機測試 
一般在模擬器中,因爲電腦內存本身較大,所以在這種情況下,即使你的程序佔用內存很高,也不會收到任何警告和異常。但是如果在iphone或者ipad上進行真機測試,因爲設備可用內存較少,所以大多數的內存問題就會暴露出來。所以提早進行真機測試是很有必要的。 
(在真機上,程序運行效率也會大大提升,在模擬器上游戲幀數10幀不到,放到真機上居然是60幀滿的,mac mini的性能真是菜啊!) 
  
6.內存警告。 
當機器內存吃緊的時候,會給程序一個內存警告消息。這個消息分爲1和2兩種等級,等級1的時候基本上問題不大。等級2的時候就要注意了,通常這時離崩潰不遠了(程序內存佔用在350M左右一般會收到等級2的警告。)。如果程序的內存佔用超過400M,基本上這時程序就會直接被操作系統殺死,表現在ipad上就是程序直接退出。而這時候程序不會打印任何有助於你檢查的log! 


----------------------------------------------------------------------------

之前項目一直在IPAD2上測試,一直很流暢。後來拿到ITOUCH上的時候,瞬間就崩了。用XCODE的內存分析工具分析,內存都快飆到200M了。。。。經過一番折騰以後,終於控制在80M以內。下邊就寫寫折騰過程中遇到的問題。


一,IOS與圖片內存--資源加載消耗

在IOS上,圖片會被自動縮放到2的N次方大小。比如一張1024*1025的圖片,佔用的內存與一張1024*2048的圖片是一致的。圖片佔用內存大小的計算的公式是;長*寬*4。這樣一張512*512 佔用的內存就是 512*512*4 = 1M。其他尺寸以此類推。(ps:IOS上支持的最大尺寸爲2048*2048)。


二,cocos2d-x 的圖片緩存

Cocos2d-x 在構造一個精靈的時候會使用spriteWithFile或者spriteWithSpriteFrameName等 無論用哪種方式,cocos2d-x都會將這張圖片加載到緩存中。如果是第一次加載這個圖片,那就會先將這張圖片加載到緩存,然後從緩存讀取。如果緩存中已經存在,則直接從緩存中提取,免除了加載過程。

圖片的緩存主要由以下兩個類來處理:CCSpriteFrameCache, CCTextureCache

CCSpriteFrameCache加載的是一張拼接過的大圖,每一個小圖只是大圖中的一個區域,這些區域信息都在plist文件中保存。用的時候只需要根據小圖的名稱就可以加載到這個區域。

CCTextureCache 是普通的圖片緩存,我們所有直接加載的圖片都會默認放到這個緩存中,以提高調用效率。

因此,每次加載一張圖片,或者通過plist加載一張拼接圖時,都會將整張圖片加載到內存中。如果不去釋放,那就會一直佔用着。


三,渲染內存。

不要以爲,計算內存時,只計算加載到緩存中的內存就可以了。以一張1024*1024的圖片爲例。

CCSprite *pSprite = CCSprite::spriteWithFile("a.png");

調用上邊這行代碼以後,可以在LEAKS工具中看到,增加了大約4M的內存。然後接着調用

addChild(pSprite);

這時,內存又增加了4M。也就是,一張圖片,如果需要渲染的話,那它所佔用的內存將要X2。


再看看通過plist加載的圖片,比如這張大圖尺寸爲2048*2048。想要加載其中的一張32*32的小圖片

CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("b.plist");

此時內存增加16M (汗)

CCSprite *pSpriteFrame = CCSprite::spriteWithSpriteFrameName("b1.png");

b.png 大小爲32*32 ,想着也就是增加一點點內存,可實際情況是增加16M內存。也就是隻要渲染了其中的一部分,那麼整張圖片都要一起被加載。

但是情況不是那麼的糟糕,這些已經渲染的圖片,如果再次加載的話,內存是不會再繼續升高的,比如又增加了100個b.plist的另一個區域,圖片內存還是共增加16+16 = 32M,而不會繼續上升。


四,緩存釋放

如果遊戲有很多場景,在切換場景的時候可以把前一個場景的內存全部釋放,防止總內存過高.

CCTextureCache::sharedTextureCache()->removeAllTextures(); 釋放到目前爲止所有加載的圖片

CCTextureCache::sharedTextureCache()->removeUnusedTextures(); 將引用計數爲1的圖片釋放掉CCTextureCache::sharedTextureCache()->removeTexture(); 單獨釋放某個圖片

CCSpriteFrameCache 與 CCTextureCache 釋放的方法差不多。

值得注意的是釋放的時機,一般在切換場景的時候釋放資源,如果從A場景切換到B場景,調用的函數順序爲B::init()---->A::exit()---->B::onEnter() 可如果使用了切換效果,比如CTransitionJumpZoom::transitionWithDuration這樣的函數,則函數的調用順序變爲B::init()---->B::onEnter()---->A::exit() 而且第二種方式會有一瞬間將兩個場景的資源疊加在一起,如果不採取過度,很可能會因爲內存吃緊而崩潰。

有時強制釋放全部資源時,會使某個正在執行的動畫失去引用而彈出異常,可以調用CCActionManager::sharedManager()->removeAllActions();來解決。


五,內存優化

優化的心得就是儘量去拼接圖片,使圖片邊長儘可能的保持2的N次方並且裝的很滿。但要注意,有邏輯關係的圖片儘量打包在一張大圖裏,另外一點就是打包的時候要考慮到層的分佈。因爲爲了渲染效率可能會用到CCSpriteBatchNode;同一個BatchNode裏的圖片都是位於一個層級的,因此必須根據各個圖片的層級關係,打包到不同的plist裏。有時內存和效率不可以兼得,只能儘量平衡了。

六,其他

最後附一個各代IOS設備的內存限制情況

設備                                              建議內存                   最大內存

iPad2/iPhone4s/iphone4                170-180mb                 512mb

iPad/iPod touch3,4/iphone3gs          40-80mb                  256mb

iPod touch1,2/iPhone3g/iPhone1         25mb                    128mb


上述建議內存只是一些人自己測試的結果,可用的RAM不大於最大內存的一半,如果程序超過最大內存的一半,則可能會掛掉。

另外在LEAKS裏查看模擬器中和真機總的內存,會有較大出入。在模擬器中的結果與實際更接近一些。


本文轉載於:http://blog.chinaunix.net/uid-20622737-id-3269694.html

發佈了7 篇原創文章 · 獲贊 7 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章