一个CCSprite所需要耗费内存分析

2024-01-30 21:38

本文主要是介绍一个CCSprite所需要耗费内存分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!



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 (
例如 1024*1024 图片占4M = 4*10^6 b 。 对于16位色-每像素16位颜色 系数是2 即2M=2*10^6b) ,例如:加载一张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创建纹理. 比如,一些内存资源比较紧缺的设备,处理非重复性图片(某些单一对话框背景)不缓存.


CCDriectro中 每次去渲染的时候!都会去查看内存释放池的是否有内存计数为0的对象!如果有的话!就会去清理掉!释放内存!(每次渲染引用计数加1)


如场景切换  在内存吃紧的情况下 我们可以选择 先清理一下缓存!

1)调用 CCDirector::sharedDirector()->purgeCachedData() 清空缓存。
2)新建场景。
3)调用 CCDirector::sharedDirector()->replaceScene(this)
 替换新场景。




这篇关于一个CCSprite所需要耗费内存分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/661623

相关文章

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

python中Hash使用场景分析

《python中Hash使用场景分析》Python的hash()函数用于获取对象哈希值,常用于字典和集合,不可变类型可哈希,可变类型不可,常见算法包括除法、乘法、平方取中和随机数哈希,各有优缺点,需根... 目录python中的 Hash除法哈希算法乘法哈希算法平方取中法随机数哈希算法小结在Python中,

Java Stream的distinct去重原理分析

《JavaStream的distinct去重原理分析》Javastream中的distinct方法用于去除流中的重复元素,它返回一个包含过滤后唯一元素的新流,该方法会根据元素的hashcode和eq... 目录一、distinct 的基础用法与核心特性二、distinct 的底层实现原理1. 顺序流中的去重

关于MyISAM和InnoDB对比分析

《关于MyISAM和InnoDB对比分析》:本文主要介绍关于MyISAM和InnoDB对比分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录开篇:从交通规则看存储引擎选择理解存储引擎的基本概念技术原理对比1. 事务支持:ACID的守护者2. 锁机制:并发控制的艺

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案(最新整理)

《MyBatisPlus中update_time字段自动填充失效的原因分析及解决方案(最新整理)》在使用MyBatisPlus时,通常我们会在数据库表中设置create_time和update... 目录前言一、问题现象二、原因分析三、总结:常见原因与解决方法对照表四、推荐写法前言在使用 MyBATis

Python主动抛出异常的各种用法和场景分析

《Python主动抛出异常的各种用法和场景分析》在Python中,我们不仅可以捕获和处理异常,还可以主动抛出异常,也就是以类的方式自定义错误的类型和提示信息,这在编程中非常有用,下面我将详细解释主动抛... 目录一、为什么要主动抛出异常?二、基本语法:raise关键字基本示例三、raise的多种用法1. 抛

Redis过期删除机制与内存淘汰策略的解析指南

《Redis过期删除机制与内存淘汰策略的解析指南》在使用Redis构建缓存系统时,很多开发者只设置了EXPIRE但却忽略了背后Redis的过期删除机制与内存淘汰策略,下面小编就来和大家详细介绍一下... 目录1、简述2、Redis http://www.chinasem.cn的过期删除策略(Key Expir

github打不开的问题分析及解决

《github打不开的问题分析及解决》:本文主要介绍github打不开的问题分析及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、找到github.com域名解析的ip地址二、找到github.global.ssl.fastly.net网址解析的ip地址三

Mysql的主从同步/复制的原理分析

《Mysql的主从同步/复制的原理分析》:本文主要介绍Mysql的主从同步/复制的原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录为什么要主从同步?mysql主从同步架构有哪些?Mysql主从复制的原理/整体流程级联复制架构为什么好?Mysql主从复制注意