zoukankan      html  css  js  c++  java
  • Cocos2d-x与ios内存管理分析(在游戏中减少内存压力)

     

    Cocos2d-x与ios内存管理分析(在游戏中减少内存压力)

    猴子原创,欢迎转载。转载请注明: 转载自Cocos2D开发网--Cocos2Dev.com,谢谢! 年

    原文地址: http://www.cocos2dev.com/?p=281

    注:自己以前也写过Cocos2d-x如何优化内存的使用,以及内存不足的情况下怎么处理游戏。今天在微博中看到有朋友介绍了下内存,挺详细的。不知道是谁写的,我记录下。

    一,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里查看模拟器中和真机总的内存,会有较大出入。在模拟器中的结果与实际更接近一些。

  • 相关阅读:
    AIMS 2013中的性能报告工具不能运行的解决办法
    读懂AIMS 2013中的性能分析报告
    在线研讨会网络视频讲座 方案设计利器Autodesk Infrastructure Modeler 2013
    Using New Profiling API to Analyze Performance of AIMS 2013
    Map 3D 2013 新功能和新API WebCast视频下载
    为Autodesk Infrastructure Map Server(AIMS) Mobile Viewer创建自定义控件
    ADN新开了云计算Cloud和移动计算Mobile相关技术的博客
    JavaScript修改css样式style
    文本编辑神器awk
    jquery 开发总结1
  • 原文地址:https://www.cnblogs.com/iOS-Blog/p/4727658.html
Copyright © 2011-2022 走看看