Just copy from
http://www.cocoachina.com/bbs/simple/?t56479.html
一个CCSprite所需要耗费内存分析
加载一张图片的过程 所发生的函数:
1.[CCSprite spriteWihtFile:@"xxxx"]; //函数内部用 CCTexureCache 创建一个CTexture2D对象.
2.[CCTexureCache sharedTexure] addImage:@"xxxx"]; //首次创建,则加载图片创建纹理,并缓存.
UImage* img = [UImage initWithContentsOfFile:@"xxxx"];//需要一些内存,这些内存是暂时的.创建纹理后被释放.
[CCTexure2D initWithImage:img];
//这个函数内部会转换图片的像素格式,并向OpenGL分配纹理需要的空间.
//分配空间大小的规则是: (2^n x 2 ^n x 4)BYTE ,例如:加载一张128*128的图片 和 加载一张 128 * 100 或 99 * 99 的图片需要的内存大小相同。
//如果加载一张513*129的图片,就会以1024*512来分配内存。
//所以这里用ZWoptex来排列所有非规则( 大小不为 2^n x 2 ^n )小图片是比较省内存的. 其实是这个
——————————————
再看看经过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,而不会继续上升。
————————————————
3.[CCTexure2D initWithData:(void*) xx]; //这个函数主要是对函数2转换后的位图数据(RGBXXXX),进行纹理加载.
//这里用到了OpenGL函数的 glGenTexures(产生一个纹理对象) glBindTexture(绑定为OPENGL当前纹理) glTexImage2D(给纹理加载位图数据)
//其中glTexImage2D内部会调用 gfxAllocateTextureLevel 函数分配内存.如果是1024*1024则是4M的大小(图片占用内存大小的共计的公式是;长*宽*4). Instruments可以监控到 内存的分配函数gfxAllocateTextureLevel.
//********* 以上是加载一张纹理的大小 ****************
//********* 以下是绘画一张纹理的大小 *****************
//OpenGL绘画纹理还需要消耗内存.
在CCSprite 的 draw 函数中:
glDrawArrays 函数内部调用 gldLoadTextureLevelBuffer . Instruments可以监控到 内存的分配函数 gldLoadTextureLevelBuffer .
这里需要的内存为:实际绘画纹理大小的规则大小.
例如:一张大小为800*600的图片 需要 1024*1024*4 = 4M 内存用于纹理加载。
如果只绘画这张图片的 某个 28*28大小的 区域, 那么还需要一个 32 * 32 *4 = 4K 大小的内存. 共用4.004M内存
如果需要绘画800*600的全部区域,则需要1024*1024 = 4M内存. 共用8M内存。也便是,一张图片,若是必要渲染的话,那它所占用的内存将要X2。
//********* 内存优化 *****************
假定游戏有不少场景,在切换场景的时刻可以把前一个场景的内存所有开释,预防总内存过高.
CCTextureCache::sharedTextureCache()->removeAllTextures(); 拘留到今朝为止所有加载的图片
CCTextureCache::sharedTextureCache()->removeUnusedTextures(); 将引用计数为1的图片开释掉CCTextureCache::sharedTextureCache()->removeTexture(); 单独囚系某个图片
1.纹理缓存 有个 purgSharedTexureCache可以删除当前纹理缓存,释放当前纹理缓存,但其他CCSprite有对纹理的引用,所以这个函数不会真的释放内存,而且再次加载已经存在的纹理的时候又需要大量内存.
不建议使用 purgSharedTexureCache. removeAllTextures也是一样的情况.
2.使用removeUnusedTexutres 来释放已经没有其他对象引用的纹理.
3.非重复性图片不建议使用CCTexureCache来缓存纹理.直接用CCTexture2D创建纹理. 比如,一些内存资源比较紧缺的设备,处理非重复性图片(某些单一对话框背景)不缓存.
如场景切换 在内存吃紧的情况下 我们可以选择 先清理一下缓存!
1)调用 CCDirector::sharedDirector()->purgeCachedData() 清空缓存。2)新建场景。
3)调用 CCDirector::sharedDirector()->replaceScene(this) 替换新场景。