Cocos2d-x 3.x:如何进行合理的内存分配(使用AutoreleasePool 来合理的管理内存)

Cocos2d-x 3.x:如何进行合理的内存分配(使用AutoreleasePool 来合理的管理内存)

本文转载至深入理解Cocos2d-x 3.x:如何进行合理的内存分配

设想如下场景,这是一个典型的内存合理分配的场景:在一帧内,有若干个函数,每个函数都会创建一系列的精灵,每个精灵都不同,都会占用一定的内存,精灵的总数可能会有1000个,而一个函数只会创建10个精灵这样,创建的精灵只会在这个函数中使用,大致代码如下:


1

2

3

4

5

for(int i = 0; i < 10; i++)  

{  

    Sprite* s = Sprite::create();  

    //-- doSomething --  

}

这样做会造成内存泄露吗?

答案是当然不会,但是这样会造成一帧内的内存峰值过高,因为在引擎的自动内存管理中,所有的释放内存操作都是在每一帧的结束才会进行的,所以就算申请的内存在这一帧中不会有其他地方会使用,它的内存也不会随着作用域的结束而释放的。

那么我们应该如何优化这段代码呢?如下


1

2

3

4

5

6

AutoreleasePool pool;  

for (int i = 0; i < 10; i++)  

{  

    Sprite* s = Sprite::create();  

    //-- doSomething --  

}

只需要在函数的第一句加上


1

AutoreleasePool pool;

就可以实现在函数结束的时候自动将create的指针释放了,那么为什么会有那么神奇的效果呢?我们来分析一下这个函数的构造函数以及析构函数,首先分析一下构造函数:


1

2

3

4

5

6

AutoreleasePool::AutoreleasePool()  

: _name("")  

{  

    _managedObjectArray.reserve(150);  

    PoolManager::getInstance()->push(this);  

}

他向PoolManager的单例中push了自己,我们进入push中看看它的具体实现


1

2

3

4

void PoolManager::push(AutoreleasePool *pool)  

{  

    _releasePoolStack.push_back(pool);  

}

直接向_releasePoolStack栈中压入了this,那这个将会起到什么效果呢?这就不得不说一下autorelease的实现了,众所周知,create函数的内存自动管理机制依赖于autorelease函数,那么autorelease函数是干嘛用的呢:


1

2

3

4

5

Ref* Ref::autorelease()  

{  

    PoolManager::getInstance()->getCurrentPool()->addObject(this);  

    return this;  

}

向某个Pool池添加对象,那么getCurrentPool获取的是那个内存管理池呢?


1

2

3

4

AutoreleasePool* PoolManager::getCurrentPool() const

{  

    return _releasePoolStack.back();  

}

就是最后我们通过push添加进来的那个池子,所以每创建一个AutoreleasePool 对象,都会压入PoolManager中。然后后续的autorelease操作是将对象加入到最新创建的AutoreleasePool 对象中。

那么最终要通过什么途径让函数在函数结束的时候自动释放内存呢?我们知道,作用域结束的时候,会调用普通对象的析构函数,那么就来看看AutoreleasePool 的析构函数执行了什么吧


1

2

3

4

5

AutoreleasePool::~AutoreleasePool()  

{  

    clear();  

    PoolManager::getInstance()->pop();  

}

第一个是clear函数,这是一个非常关键的函数,我们跟踪进去


1

2

3

4

5

6

7

8

void AutoreleasePool::clear()  

{  

    for (const auto &obj : _managedObjectArray)  

    {  

        obj->release();  

    }  

    _managedObjectArray.clear();  

}

它会将所有addObject的对象全部执行一次release操作。这样就可以实现在函数结束的时候自动释放内存了。


1

PoolManager::getInstance()->pop();

这一行代码主要是从PoolManager中将当前AutoreleasePool 对象弹出栈(因为当前对象已经析构了)

上述就是通过使用AutoreleasePool 来合理的管理内存了。

时间: 2024-08-08 06:56:35

Cocos2d-x 3.x:如何进行合理的内存分配(使用AutoreleasePool 来合理的管理内存)的相关文章

cocos2d::Vector

v3.0 beta加入 定义在"COCOS2DX_ROOT/cocos/base"的"CCVector.h"头文件中. template<class T>class CC_DLL Vector; cocos2d::Vector<T>是一个封装好的能动态增长顺序访问的容器. cocos2d::Vector<T>中的元素是按序存取的,它的低层实现数据结构是标准模版库中的标准顺序容器std::vector. 在Cocos2d-x v3.

cocos2d 如何优化内存使用

如何优化内存使用 内存优化原理 为优化应用内存使用,开发人员首先应该知道什么最耗应用内存,答案就是纹理! 纹理几乎会占据90%应用内存.所以尽量最小化应用的纹理内存使用,否则应用很有可能会因为低内存而崩溃. 本文介绍Cocos2d-x游戏通用的两条内存优化原理指导. 认识瓶颈寻找方案 什么样的纹理最耗应用内存?或这些纹理会消耗多少内存?当然这个不用手动计算,只需猜测. 工具在这里已经准备好了.使用的是苹果的工具“Allocation & Leaks”.你可以在Xcode中长按“Run”命令,选择

Cocos2d之&ldquo;引用计数&rdquo;内存管理机制实现解析

一.引言 本文主要分析cocos2d游戏开发引擎的引用计数内存管理技术的实现原理.建议读者在阅读本文之前阅读笔者之前一篇介绍如何使用cocos2d内存管理技术的文章--<Cocos2d之Ref类与内存管理使用详解>. 二.相关概念 引用计数 引用计数是计算机编程语言的一种内存管理技术,是指将资源(对象.内存或者磁盘空间等)的被引用计数保存起来,当引用计数变为零时就将资源释放的过程.使用引用计数技术可以实现自动内存管理的目的. 当实例化一个类时,对象的引用计数为1,在其他对象需要持有这个对象时,

如何优化cocos2d程序的内存使用和程序大小

在我完成第一个游戏项目的时候,我深切地意识到"使用cocos2d来制作游戏的开发者们,他们大多会被cocos2d的内存问题所困扰".而我刚开始接触cocos2d的时候,社区里面的人们讨论了一个非常有意义的话题:"请简单地讲述你认为新手cocos2d程序员在他开始编码之前,最应该先知道,或者应该关注和注意的事项."这个问题的答案很多,有人讲是"如何加载和保存游戏数据",有人讲的是"如何实现有限状态机"等等.而最吸引我的则是,有一

Cocos2d之Ref类与内存管理使用详解

一.简介 用C++和JAVA编写过程序的朋友一定会为两种语言不同的内存管理机制懊恼.JAVA程序运行在JVM之上,由JVM自动实现内存管理,开发者只管申请内存而不用手动释放内存.当JAVA中对象没有被任何引用变量(类似于C和C++的指针)引用时,JVM会将对象释放掉.C++和C一样,是编译后能够直接被操作系统执行的语言,没有虚拟机负责其内存管理,因此需要在程序中管理内存.本文主要介绍如何使用cocos2d提供的内存管理机制. Cocos2d-x借鉴了“引用计数”思想,实现了一定程度上的自动内存管

Cocos2d中的Menu使用

学习cocos2d-x中的菜单主要需要了解:菜单(CCMenu)和菜单项(CCMenuItem)以及CCMenuItem的具体子类. a. 下面来学习一下相关的类. 1. CCMenu 菜单,是CCLayer的子类,是一个层(容器),可以往里面添加菜单项.下面是它的类结构图: CCMenu默认接受触屏事件的优先级是-128(优先级很高,因为值越小,响应触屏事件的优先级越高),可以通过继承它实现自定义的效果,创建CCMenu对象的函数: static CCMenu* menuWithItems(C

iOS应用性能调优的25个建议和技巧

目录 我要给出的建议将分为三个不同的等级: 入门级. 中级和进阶级: 入门级(这是些你一定会经常用在你app开发中的建议) 1. 用ARC管理内存 2. 在正确的地方使用reuseIdentifier 3. 尽可能使Views透明 4. 避免庞大的XIB 5. 不要block主线程 6. 在Image Views中调整图片大小 7. 选择正确的Collection 8. 打开gzip压缩 中级(这些是你可能在一些相对复杂情况下可能用到的) 9. 重用和延迟加载Views 10. Cache, C

Cocos2d-x中__Dictionary容器以及实例介绍

__Dictionary类在Cocos2d-x 2.x时代它就是CCDictionary类,它是模仿Objective-C中的NSDictionary类而设计的,通过引用计数管理内存.__Dictionary继承于Ref类,因此它所能容纳的是Ref及子类所创建的对象指针. 1.创建__Dictionary对象 创建__Dictionary对象有很多函数,下面是总结常用的函数: static __Dictionary* create().创建__ Dictionary. static __Dict

iOS_31_cocos2d_CCScene

CCScene"场景", 运行游戏时需要通过 [CCDirector sharedDirector]runWithScene:<#(CCScene *)#>] 启动第一个场景,也可以通过代理的 -(CCScene *)startScene 方法,创建并返回第一个场景. 当然,游戏复杂的话,会包含很多个场景, 场景的切换,也是通过CCDirector来完成. CCScene是个抽象的概念,也没有可视化显示的功能, // // IntroScene.h // 31_cocos2

iOS每日一记之——————————iOS性能优化

写在前面 本文来自iOS Tutorial Team 的 Marcelo Fabri,他是Movile的一名 iOS 程序员.这是他的个人网站:http://www.marcelofabri.com/,你还可以在Twitter上关注@marcelofabri_. 性能对 iOS 应用的开发尤其重要,如果你的应用失去反应或者很慢,失望的用户会把他们的失望写满App Store的评论.然而由于iOS设备的限制,有时搞好性能是一件难事.开发过程中你会有很多需要注意的事项,你也很容易在做出选择时忘记考虑