coco2dx对象统计及内存查漏

前端之家收集整理的这篇文章主要介绍了coco2dx对象统计及内存查漏前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

记一次对cocos2dx的对象统计及内存泄露的历程(ps:很老的cocos版本)

对象统计思路:

为了不对引擎造成破话,都是采取帮函数指针、增加借口、多态性的方式,所以不需要再引擎中include包含统计类,当做插件set进去,类似于组件模式,扩展引擎。


1、对象创建统计

因为创建对象是通过create接口创建(先不考虑引擎内部new对象的情况,下面会说明怎么避免这个问题),这个借口里又会调用autorelease放到自动释放池中自动管理内存,所以在autorelease里放个函数指针绑定统计函数CNodeCounterLog::newNodeCount(CCObject* _node),里面写统计逻辑

2、对象销毁统计

对象销毁调用的是release,里面会判断引用计数是否为0,0则销毁,所以在这里也放个函数指针绑定统计函数CNodeCounterLog::deleteNodeCount(CCObject* _node) ,里面写统计逻辑

3、统计逻辑里面获取对象及其大小:

可以通过typeid(*_node).name()获取到对象的名称,大小的话sizeof(*_node)获取不到的,不像java可以通过反射获取到对象。所以就定了个反射列表来获取对应的大小:

if (_name == CC_LuaStack) return sizeof(CCLuaStack){}
else if (_name == CC_String) return sizeof(CCString){}
else //为了防止遗漏,把未在反射列表的对象写到本地记录一下
{
char tmp[128];
sprintf(tmp,“——- not found class:%s\n”,_name.c_str());
CCLOG(“%s”,tmp);
CNodeCounterLog::GetInstance()->log(tmp); //未添加经列表的写到日志中,方便添加
return -1;
}

信息结构体
对象名、个数、总大小,对象指针的集合vector

4、统计贴图纹理对象占用的内存:

再纹理缓存集合CCTextureCache中增加个借口让统计调用获取缓存集合textures,遍历textures,
每个对象的占用计算结果 = width * height * 每个像素格式占用位数 / 8.f,单位byte

5、统计字体纹理对象占用的内存:

直接从统计集合中获取到ccLabelTTF在获取其纹理计算,公式同上。

6、统计lua占用内存:

在lua脚本引擎中增加获取大小的借口即可,

int CCLuaEngine::getMemSize()
{
lua_State* state = m_stack->getLuaState();
return state ? lua_gc(state,LUA_GCCOUNT,0) : 0;
}

7、实时绘制信息:

利用多态性,统计类继承CCNode,重写visit函数,然后在CCDirector加个CCNode节点,把统计类set进去,每帧调用这个CCNode的visit。

8、规避引擎内不统一的写法造成统计统计错误的问题:

引擎内部有些地方使用new来创建对象,release销毁对象,会造成统计类里对象不增加,但会减少的情况。所以为了避免这个问题,在CCObject中增加了个标记,只要调用了autorelease进入统计的对象就标记一下,减少的时候判断一下该对象是否为标记过得对象,否则不进入统计逻辑直接返回。

9、黑白名单模式:

通过黑白名单来决定对象是否需要统计,减少不必要的对象统计或者具体统计某些对象。


内存泄露查找

反复打开关闭某个界面几次,看对象统计的总和是否不断增加,如果是则有对象泄露(增量是一样的)。

内存泄露定位

查看是开的是哪个xxx.json,命令行有log,即可查找到对用的lua文件
搜索一下有retain的相关代码,注释掉后再次测一下,如果恢复正常则可以判断是忘了release
搜索一下有removeFromParentAndCleanup(false)的代码,改为true后恢复正常(removeFromParentAndCleanup里面是stopAll定时器、动画)

可以在vs装上lua调试插件BabeLua, 断点追踪,看下创建时和销毁时的地址是否一致


有图有真相


附上代码

CCNodeCounterDef.h

#ifndef __NODE_DEFINE_H__
#define __NODE_DEFINE_H__

#include <vector>
#include <string>

#define CC_LuaStack "CCLuaStack"
#define CC_String "CCString"
#define CC_Array "CCArray"
#define CC_Bool "CCBool"
#define CC_Integer "CCInteger"
#define CC_LabelAtlas "CCLabelAtlas"
#define CC_TextureAtlas "CCTextureAtlas"
#define CC_Texture2D "CCTexture2D"
#define CC_Dictionary "CCDictionary"
#define CC_HTTPRequest "CCHTTPRequest"
#define CC_Image "CCImage"
#define CC_Sprite "CCSprite"
#define CC_GraySprite "CCGraySprite"
#define CC_Scene "CCScene"
#define CC_LabelTTF "CCLabelTTF"
#define CC_NodeRGBA "CCNodeRGBA"
#define CC_TargetedTouchHandler "CC_TargetedTouchHandler"
#define CC_UIButton "UIButton"
#define CC_Scale9Sprite "CCScale9Sprite"
#define CC_GUIRenderer "GUIRenderer"
#define CC_SpriteBatchNode "CCSpriteBatchNode"
#define CC_Timer "CCTimer"
#define CC_Layer "CCLayer"
#define CC_LayerRGBA "CCLayerRGBA"
#define CC_DrawNode "CCDrawNode"
#define CC_TexturePVR "CCTexturePVR"
#define CC_UILayer "UILayer"
#define CC_UIRootWidget "UIRootWidget"
#define CC_UILabel "UILabel"
#define CC_SchedulerScriptHandlerEntry "CCSchedulerScriptHandlerEntry"
#define CC_NotificationObserver "CCNotificationObserver"
#define CC_UIRectClippingNode "UIRectClippingNode"
#define CC_ProgressTimer "CCProgressTimer"
#define CC_DelayTime "CCDelayTime"
#define CC_Sequence "CCSequence"
#define CC_ZipFile "CCZipFile"
#define CC_AutoreleasePool "CCAutoreleasePool"
#define CC_CallFunc "CCCallFunc"
#define CC_TargetedTouchHandler "CCTargetedTouchHandler"
#define CC_Touch "CCTouch"
#define CC_BMFontConfiguration "CCBMFontConfiguration"
#define CC_LabelBMFont "CCLabelBMFont"
#define CC_Color3bObject "CCColor3bObject"
#define CC_ClippingRegionNode "CCClippingRegionNode"
#define CC_Invocation "CCInvocation"
#define CC_EditBox "CCEditBox"
#define CC_Set "CCSet"
#define CC_MenuItemSprite "CCMenuItemSprite"
#define CC_Menu "CCMenu"
#define CC_ProgressTo "CCProgressTo"
#define CC_AnimationConf "AnimationConf"
#define CC_UILayout "UILayout"
#define CC_UIImageView "UIImageView"
#define CC_UILabelBMFont "UILabelBMFont"
#define CC_MoveToPX "CCMoveToPX"
#define CC_MoveTo "CCMoveTo"
#define CC_FadeOut "CCFadeOut"
#define CC_MoveBy "CCMoveBy"
#define CC_Node "CCNode"
#define CC_AnimationFrame "CCAnimationFrame"
#define CC_Animation "CCAnimation"
#define CC_QtzSprite "QtzSprite"
#define CC_CallFuncN "CCCallFuncN"
#define CC_Animation222 "Animation"
#define CC_Display "Display"
#define CC_Joint "Joint"
#define CC_QtzBone "QtzBone"
#define CC_Animate "CCAnimate"
#define CC_RepeatForever "CCRepeatForever"
#define CC_AnimationClip "AnimationClip"
#define CC_RotateTo "CCRotateTo"
#define CC_QtzZOrderNode "QtzZOrderNode"
#define CC_QtzBoneAnimation "QtzBoneAnimation"
#define CC_ScaleTo "CCScaleTo"
#define CC_Repeat "CCRepeat"
#define CC_Spawn "CCSpawn"
#define CC_FadeTo "CCFadeTo"
#define CC_TintTo "CCTintTo"
#define CC_UIWidget "UIWidget"
#define CC_TouchScriptHandlerEntry "CCTouchScriptHandlerEntry"
#define CC_JumpTo "CCJumpTo"
#define CC_ParticleSystemQuad "CCParticleSystemQuad"
#define CC_EaseExponentialOut "CCEaseExponentialOut"
#define CC_StandardTouchHandler "CCStandardTouchHandler"
#define CC_TintBy "CCTintBy"
#define CC_EaseBackOut "CCEaseBackOut"
#define CC_LayerColor "CCLayerColor"
#define CC_SpriteFrame "CCSpriteFrame"
#define CC_UILoadingBar "UILoadingBar"
#define CC_FadeIn "CCFadeIn"
#define CC_QParticleSpriteQuad "QParticleSpriteQuad"
#define CC_ScaleBy "CCScaleBy"
#define CC_UIListView "UIListView"
#define CC_EaseBackIn "CCEaseBackIn"
#define CC_UILinearLayoutParameter "UILinearLayoutParameter"
#define CC_Show "CCShow"
#define CC_Hide "CCHide"
#define CC_UICheckBox "UICheckBox"
#define CC_UIListViewEx "UIListViewEx"
#define CC_UIListViewSmartAlign "UIListViewSmartAlign"
#define CC_UICCTextField "UICCTextField"
#define CC_UIRelativeLayoutParameter "UIRelativeLayoutParameter"
#define CC_OrbitCamera "CCOrbitCamera"
#define CC_UIScrollView "UIScrollView"
#define CC_UITextField "UITextField"
#define CC_RichText "RichText"

/****************** gloable singleton #define CC_GLProgram "CCGLProgram" #define CC_Configuration "CCConfiguration" #define CC_NotificationCenter "CCNotificationCenter" #define CC_ArmatureDataManager "CCArmatureDataManager" #define CC_DisplayLinkDirector "CCDisplayLinkDirector" #define CC_Scheduler "CCScheduler" #define CC_ActionManager "CCActionManager" #define CC_TouchDispatcher "CCTouchDispatcher" #define CC_KeypadDispatcher "CCKeypadDispatcher" #define CC_ShaderCache "CCShaderCache" #define CC_TextureCache "CCTextureCache" #define CC_SpriteFrameCache "CCSpriteFrameCache" */
std::vector<std::string>    gBlackList;
std::vector<std::string>    gWhiteList;
void gInitBlackList()
{
    //gBlackList.push_back(CC_LuaStack);
    //gBlackList.push_back(CC_String);
    gBlackList.push_back(CC_Array);
    //gBlackList.push_back(CC_Bool);
    //gBlackList.push_back(CC_Integer);
    //gBlackList.push_back(CC_LabelAtlas);
    //gBlackList.push_back(CC_TextureAtlas);
    gBlackList.push_back(CC_Texture2D);
    //gBlackList.push_back(CC_Dictionary);
    //gBlackList.push_back(CC_HTTPRequest);
    //gBlackList.push_back(CC_Image);
    //gBlackList.push_back(CC_Sprite);
    //gBlackList.push_back(CC_GraySprite);
    //gBlackList.push_back(CC_Scene);
    //gBlackList.push_back(CC_LabelTTF);
    //gBlackList.push_back(CC_NodeRGBA);
    //gBlackList.push_back(CC_TargetedTouchHandler);
    //gBlackList.push_back(CC_UIButton);
    //gBlackList.push_back(CC_Scale9Sprite);
    //gBlackList.push_back(CC_GUIRenderer);
    //gBlackList.push_back(CC_SpriteBatchNode);
    gBlackList.push_back(CC_Timer);//sssssssss
    //gBlackList.push_back(CC_Layer);
    //gBlackList.push_back(CC_LayerRGBA);
    //gBlackList.push_back(CC_DrawNode);
    //gBlackList.push_back(CC_TexturePVR);
    //gBlackList.push_back(CC_UILayer);
    //gBlackList.push_back(CC_UIRootWidget);
    //gBlackList.push_back(CC_UILabel);
    gBlackList.push_back(CC_SchedulerScriptHandlerEntry); //sssssssss
    //gBlackList.push_back(CC_NotificationObserver);
    //gBlackList.push_back(CC_UIRectClippingNode);
    //gBlackList.push_back(CC_ProgressTimer);
    gBlackList.push_back(CC_DelayTime);//sssssssss
    //gBlackList.push_back(CC_Sequence);
    gBlackList.push_back(CC_ZipFile);
    gBlackList.push_back(CC_AutoreleasePool);
    gBlackList.push_back(CC_CallFunc);
    gBlackList.push_back(CC_TargetedTouchHandler);
    gBlackList.push_back(CC_Touch);
    gBlackList.push_back(CC_BMFontConfiguration);
    //gBlackList.push_back(CC_LabelBMFont);
    //gBlackList.push_back(CC_Color3bObject);
    gBlackList.push_back(CC_ClippingRegionNode);
    gBlackList.push_back(CC_Invocation);
    //gBlackList.push_back(CC_EditBox);
    gBlackList.push_back(CC_Set);
    //gBlackList.push_back(CC_MenuItemSprite);
    //gBlackList.push_back(CC_Menu);
    gBlackList.push_back(CC_ProgressTo);
    gBlackList.push_back(CC_AnimationConf);
    //gBlackList.push_back(CC_UILayout);
    //gBlackList.push_back(CC_UIImageView);
    //gBlackList.push_back(CC_UILabelBMFont);
    gBlackList.push_back(CC_MoveToPX);
    gBlackList.push_back(CC_MoveTo);
    gBlackList.push_back(CC_FadeOut);
    gBlackList.push_back(CC_MoveBy);
    gBlackList.push_back(CC_Node);
    gBlackList.push_back(CC_AnimationFrame);
    gBlackList.push_back(CC_Animation);
    //gBlackList.push_back(CC_QtzSprite);
    gBlackList.push_back(CC_CallFuncN);
    gBlackList.push_back(CC_Animation222);
    gBlackList.push_back(CC_Display);
    gBlackList.push_back(CC_Joint);
    //gBlackList.push_back(CC_QtzBone);
    gBlackList.push_back(CC_Animate);
    gBlackList.push_back(CC_RepeatForever);
    gBlackList.push_back(CC_AnimationClip);
    //gBlackList.push_back(CC_RotateTo);
    //gBlackList.push_back(CC_QtzZOrderNode);
    //gBlackList.push_back(CC_QtzBoneAnimation);
    gBlackList.push_back(CC_ScaleTo);
    gBlackList.push_back(CC_Repeat);
    gBlackList.push_back(CC_Spawn);
    gBlackList.push_back(CC_FadeTo);
    gBlackList.push_back(CC_TintTo);
    //gBlackList.push_back(CC_UIWidget);
    gBlackList.push_back(CC_TouchScriptHandlerEntry);
    gBlackList.push_back(CC_JumpTo);
    gBlackList.push_back(CC_ParticleSystemQuad);
    gBlackList.push_back(CC_EaseExponentialOut);
    gBlackList.push_back(CC_StandardTouchHandler);
    gBlackList.push_back(CC_TintBy);
    gBlackList.push_back(CC_EaseBackOut);
    gBlackList.push_back(CC_LayerColor);
    //gBlackList.push_back(CC_SpriteFrame);
    //gBlackList.push_back(CC_UILoadingBar);
    gBlackList.push_back(CC_FadeIn);
    gBlackList.push_back(CC_QParticleSpriteQuad);
    gBlackList.push_back(CC_ScaleBy);
    //gBlackList.push_back(CC_UIListView);
    gBlackList.push_back(CC_EaseBackIn);
    gBlackList.push_back(CC_UILinearLayoutParameter);
    gBlackList.push_back(CC_Show);
    gBlackList.push_back(CC_Hide);
    //gBlackList.push_back(CC_UICheckBox);
    //gBlackList.push_back(CC_UIListViewEx);
    gBlackList.push_back(CC_UIListViewSmartAlign);
    //gBlackList.push_back(CC_UICCTextField);
    gBlackList.push_back(CC_UIRelativeLayoutParameter);
    gBlackList.push_back(CC_OrbitCamera);
    //gBlackList.push_back(CC_LabelTTF);
}

void gInitWhiteList()
{
    //gWhiteList.push_back(CC_RichText);
    gWhiteList.push_back(CC_LabelTTF);
    gWhiteList.push_back(CC_UILabel);
    gWhiteList.push_back(CC_Sprite);
    //gWhiteList.push_back(CC_Scale9Sprite);
    gWhiteList.push_back(CC_GUIRenderer);
    gWhiteList.push_back(CC_UIImageView);
    gWhiteList.push_back(CC_LabelBMFont);
    gWhiteList.push_back(CC_HTTPRequest);
    //gWhiteList.push_back(CC_Texture2D);

}

#endif

CCNodeCounter.h

#ifndef __NODE_COUNTER_H__
#define __NODE_COUNTER_H__ 

#include <iostream>
#include <vector>
#include <map>

#include "cocos2d.h"

/* * 改动文件 * CCDirector * CCObject * CCTextureCache * CCTexture2D * CCLuaEngine * GUIReader * document.h */

struct NodeInfo
{
    NodeInfo() : mName(""),mCounter(0),mTotalSize(0),mPerSize(0)
    {
    }
    std::string             mName;
    int                     mCounter;
    int                     mTotalSize;
    int                     mPerSize;
    std::vector<cocos2d::CCObject*> mPtrVec;
};

class CNodeCounterLog : public cocos2d::CCNode
{
public:
    CNodeCounterLog();
    virtual ~CNodeCounterLog();

    static CNodeCounterLog* GetInstance();
    static CNodeCounterLog* gNodeCounterLog;

    void            destory();
    void            initFunc();
    void            initHUD();
    void            initShowBtn();

    static void     newNodeCount(cocos2d::CCObject* _node);
    void            increaseFunc(const std::string _name,int size,cocos2d::CCObject* obj);
    static void     deleteNodeCount(cocos2d::CCObject* _node);
    void            decreaseFunc(const std::string _name,cocos2d::CCObject* obj);
    bool            isBeTraced(const std::string& _name,CCObject* _node,bool _isIncrease);
    bool            isBlackList(const std::string& _name) const;
    bool            isWhiteList(const std::string& _name) const;
    std::string     getTypeName(const cocos2d::CCObject* _node) const; //获取类型名字符串
    std::map<std::string,NodeInfo*>&       getNodeMap() { return mNodeMap; }

    //提供lua掉的接口
    void            setOpen(bool _open) const;
    void            setShowAll(bool _b);
    void            setWhiteCheck(bool _b) { mIsWhite = _b; }
    bool            isWhiteCheck() const { return mIsWhite; }
    void            log(const std::string& _str = ""); //写到本地log

    virtual void    visit() override;//利用node的visit绘制信息
    void            getInfo(std::string& _info,std::string& _info2);
    void            getTextureInfo(std::string& _info,float& _size);
    void            getCCLabelTextureInfo(std::string& _info,NodeInfo* _nodeInfo,float& _size);
    void            getLuaInfo(std::string& _info,float& _size);
    void            getJsonInfo(std::string& _info,float& _size);

private:
    typedef std::map<std::string,NodeInfo*> StrNodeMap;
    StrNodeMap                          mNodeMap;
    bool                                mIsWhite;
    bool                                mShowAll;

    cocos2d::CCNode*                    mParentNode;
    cocos2d::CCLayerColor*              mLayer;
    cocos2d::CCLabelTTF*                mLabelInfo;
    cocos2d::CCLabelTTF*                mLabelInfo2;
};

#define Get_NodeCounter() CNodeCounterLog::GetInstance();

#endif

CCNodeCounter.cpp

#include "CCNodeCounter.h"
#include "cocos2d.h"
#include <typeinfo>
#include "CCNodeCounterDef.h"
#include <fstream> 
#include <algorithm>

#include "CCLuaStack.h"
#include "network/CCHTTPRequest.h"
#include "CocosGUI.h"
#include "CCScale9Sprite.h"
#include "platform/CCZipFile.h"
#include "GUI/BaseClasses/UIWidget.h"
#include "GUI/CCEditBox/CCEditBox.h"
#include "QtzAnimation/AnimationData.h"
#include "QtzAnimation/AnimationClip.h"
#include "QtzAnimation/Animation.h"
#include "QtzAnimation/Display.h"
#include "QtzAnimation/Joint.h"

USING_NS_CC;
USING_NS_CC_EXTRA;
USING_NS_CC_EXT;

const static std::string gCocosNS   =   "::";
const static std::string logFile    =   "d:\\a_counterLog.lua";
const static std::string gLogFormat = "--- [num=%6d] [size=%8.2fkb] [%s]\n";
const static std::string gLogFormatTexture = "--- [num=%6d] [size=%8.2fmb] [%s]\n";
const static std::string gLogTotal = "------- [totalNum=%8u] [totalSize=%10.2lfmb]\n";
const static std::string gLogTotalMemSize = "------- [total Mem=%8.2fmb]\n";
const static int gChangeLine        =    18;

static int GetSizeByName(const std::string& _name)
{
    if (_name == CC_LuaStack) return sizeof(CCLuaStack);
    else if (_name == CC_String) return sizeof(CCString);
    else if (_name == CC_Array) return sizeof(CCArray);
    else if (_name == CC_Bool) return sizeof(CCBool);
    else if (_name == CC_Bool) return sizeof(CCBool);
    else if (_name == CC_Integer) return sizeof(CCInteger);
    else if (_name == CC_LabelAtlas) return sizeof(CCLabelAtlas);
    else if (_name == CC_TextureAtlas) return sizeof(CCTextureAtlas);
    else if (_name == CC_Texture2D) return sizeof(CCTexture2D);
    else if (_name == CC_Dictionary) return sizeof(CCDictionary);
    else if (_name == CC_HTTPRequest) return sizeof(CCHTTPRequest);
    else if (_name == CC_Image) return sizeof(CCImage);
    else if (_name == CC_Sprite) return sizeof(CCSprite);
    else if (_name == CC_GraySprite) return sizeof(CCGraySprite);
    else if (_name == CC_Scene) return sizeof(CCScene);
    else if (_name == CC_LabelTTF) return sizeof(CCLabelTTF);
    else if (_name == CC_NodeRGBA) return sizeof(CCNodeRGBA);
    else if (_name == CC_TargetedTouchHandler) return sizeof(CCTargetedTouchHandler);
    else if (_name == CC_UIButton) return sizeof(UIButton);
    else if (_name == CC_Scale9Sprite) return sizeof(CCScale9Sprite);
    else if (_name == CC_GUIRenderer) return sizeof(GUIRenderer);
    else if (_name == CC_SpriteBatchNode) return sizeof(CCSpriteBatchNode);
    else if (_name == CC_Timer) return sizeof(CCTimer);
    else if (_name == CC_Layer) return sizeof(CCLayer);
    else if (_name == CC_LayerRGBA) return sizeof(CCLayerRGBA);
    else if (_name == CC_DrawNode) return sizeof(CCDrawNode);
    else if (_name == CC_TexturePVR) return sizeof(CCTexturePVR);
    else if (_name == CC_UILayer) return sizeof(UILayer);
    else if (_name == CC_UIRootWidget) return sizeof(UIRootWidget);
    else if (_name == CC_UILabel) return sizeof(UILabel);
    else if (_name == CC_SchedulerScriptHandlerEntry) return sizeof(CCSchedulerScriptHandlerEntry);
    else if (_name == CC_NotificationObserver) return sizeof(CCNotificationObserver);
    else if (_name == CC_UIRectClippingNode) return sizeof(UIRectClippingNode);
    else if (_name == CC_ProgressTimer) return sizeof(CCProgressTimer);
    else if (_name == CC_DelayTime) return sizeof(CCDelayTime);
    else if (_name == CC_Sequence) return sizeof(CCSequence);
    else if (_name == CC_ZipFile) return sizeof(CCZipFile);
    else if (_name == CC_AutoreleasePool) return sizeof(CCAutoreleasePool);
    else if (_name == CC_CallFunc) return sizeof(CCCallFunc);
    else if (_name == CC_TargetedTouchHandler) return sizeof(CCTargetedTouchHandler);
    else if (_name == CC_Touch) return sizeof(CCTouch);
    else if (_name == CC_BMFontConfiguration) return sizeof(CCBMFontConfiguration);
    else if (_name == CC_LabelBMFont) return sizeof(CCLabelBMFont);
    else if (_name == CC_Color3bObject) return sizeof(CCColor3bObject);
    else if (_name == CC_ClippingRegionNode) return sizeof(CCClippingRegionNode);
    else if (_name == CC_Invocation) return sizeof(CCInvocation);
    else if (_name == CC_EditBox) return sizeof(CCEditBox);
    else if (_name == CC_Set) return sizeof(CCSet);
    else if (_name == CC_MenuItemSprite) return sizeof(CCMenuItemSprite);
    else if (_name == CC_Menu) return sizeof(CCMenu);
    else if (_name == CC_ProgressTo) return sizeof(CCProgressTo);
    else if (_name == CC_AnimationConf) return sizeof(AnimationConf);
    else if (_name == CC_UILayout) return sizeof(UILayout);
    else if (_name == CC_UIImageView) return sizeof(UIImageView);
    else if (_name == CC_UILabelBMFont) return sizeof(UILabelBMFont);
    else if (_name == CC_MoveToPX) return sizeof(CCMoveToPX);
    else if (_name == CC_MoveTo) return sizeof(CCMoveTo);
    else if (_name == CC_FadeOut) return sizeof(CCFadeOut);
    else if (_name == CC_MoveBy) return sizeof(CCMoveBy);
    else if (_name == CC_Node) return sizeof(CCNode);
    else if (_name == CC_AnimationFrame) return sizeof(CCAnimationFrame);
    else if (_name == CC_Animation) return sizeof(CCAnimation);
    else if (_name == CC_QtzSprite) return sizeof(QtzSprite);
    else if (_name == CC_CallFuncN) return sizeof(CCCallFuncN);
    else if (_name == CC_Animation222) return sizeof(Animation);
    else if (_name == CC_Display) return sizeof(Display);
    else if (_name == CC_Joint) return sizeof(Joint);
    else if (_name == CC_QtzBone) return sizeof(QtzBone);
    else if (_name == CC_Animate) return sizeof(CCAnimate);
    else if (_name == CC_RepeatForever) return sizeof(CCRepeatForever);
    else if (_name == CC_AnimationClip) return sizeof(AnimationClip);
    else if (_name == CC_RotateTo) return sizeof(CCRotateTo);
    else if (_name == CC_QtzZOrderNode) return sizeof(QtzZOrderNode);
    else if (_name == CC_QtzBoneAnimation) return sizeof(QtzBoneAnimation);
    else if (_name == CC_ScaleTo) return sizeof(CCScaleTo);
    else if (_name == CC_Repeat) return sizeof(CCRepeat);
    else if (_name == CC_Spawn) return sizeof(CCSpawn);
    else if (_name == CC_FadeTo) return sizeof(CCFadeTo);
    else if (_name == CC_TintTo) return sizeof(CCTintTo);
    else if (_name == CC_UIWidget) return sizeof(UIWidget);
    else if (_name == CC_TouchScriptHandlerEntry) return sizeof(CCTouchScriptHandlerEntry);
    else if (_name == CC_JumpTo) return sizeof(CCJumpTo);
    else if (_name == CC_ParticleSystemQuad) return sizeof(CCParticleSystemQuad);
    else if (_name == CC_EaseExponentialOut) return sizeof(CCEaseExponentialOut);
    else if (_name == CC_StandardTouchHandler) return sizeof(CCStandardTouchHandler);
    else if (_name == CC_TintBy) return sizeof(CCTintBy);
    else if (_name == CC_EaseBackOut) return sizeof(CCEaseBackOut);
    else if (_name == CC_LayerColor) return sizeof(CCLayerColor);
    else if (_name == CC_SpriteFrame) return sizeof(CCSpriteFrame);
    else if (_name == CC_UILoadingBar) return sizeof(UILoadingBar);
    else if (_name == CC_FadeIn) return sizeof(CCFadeIn);
    else if (_name == CC_QParticleSpriteQuad) return sizeof(QParticleSpriteQuad);
    else if (_name == CC_ScaleBy) return sizeof(CCScaleBy);
    else if (_name == CC_UIListView) return sizeof(UIListView);
    else if (_name == CC_EaseBackIn) return sizeof(CCEaseBackIn);
    else if (_name == CC_UILinearLayoutParameter) return sizeof(UILinearLayoutParameter);
    else if (_name == CC_Show) return sizeof(CCShow);
    else if (_name == CC_Hide) return sizeof(CCHide);
    else if (_name == CC_UICheckBox) return sizeof(UICheckBox);
    else if (_name == CC_UIListViewEx) return sizeof(UIListViewEx);
    else if (_name == CC_UIListViewSmartAlign) return sizeof(UIListViewSmartAlign);
    else if (_name == CC_UICCTextField) return sizeof(UICCTextField);
    else if (_name == CC_UIRelativeLayoutParameter) return sizeof(UIRelativeLayoutParameter);
    else if (_name == CC_OrbitCamera) return sizeof(CCOrbitCamera);
    else if (_name == CC_UIScrollView) return sizeof(UIScrollView);
    else if (_name == CC_UITextField) return sizeof(UITextField);
    else
    {
        char tmp[128];
        sprintf(tmp,"------- not found class:%s\n",_name.c_str());
        CCLOG("%s",tmp);
        CNodeCounterLog::GetInstance()->log(tmp); //未添加经列表的写到日志中,方便添加
        return -1;
    }
}

CNodeCounterLog* CNodeCounterLog::gNodeCounterLog = NULL;

CNodeCounterLog::CNodeCounterLog() 
: mIsWhite(false),mParentNode(NULL),mLabelInfo(NULL),mLabelInfo2(NULL),mShowAll(true)
{
    mNodeMap.clear();
}

CNodeCounterLog::~CNodeCounterLog()
{
    for (StrNodeMap::iterator iter = mNodeMap.begin(); iter != mNodeMap.end(); ++iter)
    {
        if (iter->second != nullptr)
            delete iter->second;
    }
    setOpen(false);
    CCDirector::sharedDirector()->setNodeCounter(NULL);
    mNodeMap.clear();
    mLayer->removeFromParentAndCleanup(true);
    mLabelInfo->removeFromParentAndCleanup(true);
    mLabelInfo2->removeFromParentAndCleanup(true);
    //TODO: 不知道为啥析构时这里老是蹦,所以上面释放子节点
    //CC_SAFE_RELEASE(mParentNode); 
}

CNodeCounterLog* CNodeCounterLog::GetInstance()
{
    if (!gNodeCounterLog)
    {
        gNodeCounterLog = new CNodeCounterLog();
        gNodeCounterLog->initFunc();
    }
    return gNodeCounterLog;
}

void CNodeCounterLog::destory()
{
    if (gNodeCounterLog)
    {
        delete gNodeCounterLog;
        gNodeCounterLog = NULL;
    }
}

void CNodeCounterLog::initFunc()
{
    setOpen(true);
    setWhiteCheck(false);
    gInitBlackList();
    gInitWhiteList();
    initHUD();

    CCDirector::sharedDirector()->setNodeCounter(this); //将这个类作为插件设置进去,以便每帧调用visit绘制
}

void CNodeCounterLog::initHUD()
{
    mParentNode = CCNode::create();
    mParentNode->retain();//retain父节点就行

    float scale = 1.5f;
    float alpha = 255.f;
    ccColor3B fontc = ccc3(255.f,255.f,255.f);
    CCSize size = CCDirector::sharedDirector()->getWinSize();

    mLayer = CCLayerColor::create(ccc4(0.f,0.f,100.f),size.width,size.height);
    mLayer->setAnchorPoint(ccp(0.f,0.f));
    mLayer->setPosition(ccp(0.f,0.f));

    mLabelInfo = CCLabelTTF::create();
    mLabelInfo->setAnchorPoint(ccp(0.f,1.f));
    mLabelInfo->setPosition(ccp(0.f,size.height));
    mLabelInfo->setScale(scale);
    mLabelInfo->setOpacity(alpha);
    mLabelInfo->setColor(fontc);

    mLabelInfo2 = CCLabelTTF::create();
    mLabelInfo2->setAnchorPoint(ccp(0.f,1.f));
    mLabelInfo2->setPosition(ccp(size.width/2.f,size.height));
    mLabelInfo2->setScale(scale);
    mLabelInfo2->setOpacity(alpha);
    mLabelInfo2->setColor(fontc);

    mParentNode->addChild(mLayer);
    mParentNode->addChild(mLabelInfo);
    mParentNode->addChild(mLabelInfo2);
}

void CNodeCounterLog::setOpen(bool _open) const
{
    if (_open)
    {
        void(*pfunNew)(CCObject*) = &CNodeCounterLog::newNodeCount;
        void(*pfunDelete)(CCObject*) = &CNodeCounterLog::deleteNodeCount;
        CCObject::SetNodeCounterFunc(pfunNew,pfunDelete); //绑定函数到ccobject中
    }
    else
    {
        CCObject::SetNodeCounterFunc(NULL,NULL);
    }
}

void CNodeCounterLog::setShowAll(bool _b)
{
    mShowAll = _b;
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    if (_b)
    {
        mLayer->setContentSize(CCSize(size.width,size.height));
        mLayer->setPosition(0.f,0.f);
    }
    else
    {
        float width = 400.f;
        float height = 130.f;
        mLayer->setContentSize(CCSize(width,height));
        mLayer->setPosition(0.f,size.height - height);
    }

}

void CNodeCounterLog::newNodeCount(CCObject* _node)
{
    CNodeCounterLog* pLog = CNodeCounterLog::GetInstance();
    std::string typName(pLog->getTypeName(_node));
    _node->mIsAutoRelease = true;

    if (pLog->isWhiteCheck())
    {
        if (!pLog->isWhiteList(typName))
            return;
    }
    else
    {
        if (pLog->isBlackList(typName)) 
            return;
    }

    int size = ::GetSizeByName(typName);
    pLog->increaseFunc(typName,size,_node);
}

void CNodeCounterLog::increaseFunc(const std::string _name,CCObject* obj)
{
    CNodeCounterLog* pLog = CNodeCounterLog::GetInstance();
    StrNodeMap& nodeMap = pLog->getNodeMap();

    isBeTraced(_name,obj,true);

    bool isExist = false;
    for (StrNodeMap::iterator iter = nodeMap.begin(); iter != nodeMap.end(); ++iter)
    {
        if (_name == iter->first)
        {
            NodeInfo* nodeInfo = iter->second;
            nodeInfo->mCounter++;
            nodeInfo->mTotalSize += size;
            nodeInfo->mPtrVec.push_back(obj);
            isExist = true;
            break;
        }
    }
    if (!isExist)// 不存在,新建
    {
        NodeInfo* newNodeInfo = new NodeInfo();
        newNodeInfo->mName = _name;
        newNodeInfo->mCounter = 1;
        newNodeInfo->mTotalSize = size;
        newNodeInfo->mPerSize = size;
        newNodeInfo->mPtrVec.push_back(obj);
        nodeMap.insert(std::make_pair(_name,newNodeInfo));
    }
}

void CNodeCounterLog::deleteNodeCount(CCObject* _node)
{
    if (!_node->mIsAutoRelease)
        return;

    CNodeCounterLog* pLog = CNodeCounterLog::GetInstance();
    std::string typName(pLog->getTypeName(_node));
    if (pLog->isWhiteCheck())
    {
        if (!pLog->isWhiteList(typName))
            return;
    }
    else
    {
        if (pLog->isBlackList(typName))
            return;
    }

    int size = ::GetSizeByName(typName);
    pLog->decreaseFunc(typName,_node);
}

void CNodeCounterLog::decreaseFunc(const std::string _name,false);

    for (StrNodeMap::iterator iter = nodeMap.begin(); iter != nodeMap.end(); ++iter)
    {
        if (_name == iter->first)
        {
            NodeInfo* nodeInfo = iter->second;
            nodeInfo->mCounter--;
            nodeInfo->mTotalSize -= size;
            for (std::vector<CCObject*>::iterator ptrIter = nodeInfo->mPtrVec.begin(); ptrIter != nodeInfo->mPtrVec.end(); ++ptrIter)
            {
                if (*ptrIter == obj)
                {
                    nodeInfo->mPtrVec.erase(ptrIter);
                    break;
                }
            }

            if (nodeInfo->mCounter == 0)
                nodeMap.erase(iter);
            break;
        }
    }
}

//追踪具体的某个对象
bool CNodeCounterLog::isBeTraced(const std::string& _name,bool _isIncrease)
{
    return false;

    const char* tmp = _name.c_str();
    //if (strcmp(tmp,CC_UILayout) == 0)
    //{
    // UIWidget* layout = dynamic_cast<UIWidget*>(_node);
    // if (layout)
    // {
            char logStr[128] = { 0 };
            if (_isIncrease)
                sprintf(logStr,"--- Increase %s\t\t:0x%x\n",tmp,_node);
            else
                sprintf(logStr,"--- Decrease %s\t\t:0x%x\n",_node);
            log(logStr);

    // return true;
    // }
    //}
    return false;
}

bool CNodeCounterLog::isBlackList(const std::string& _name) const
{
    for (std::vector<std::string>::const_iterator iter = gBlackList.begin(); iter != gBlackList.end(); ++iter)
    {
        if (_name == *iter)
            return true;
    }
    return false;
}

bool CNodeCounterLog::isWhiteList(const std::string& _name) const
{
    for (std::vector<std::string>::const_iterator iter = gWhiteList.begin(); iter != gWhiteList.end(); ++iter)
    {
        if (_name == *iter)
            return true;
    }
    return false;
}

std::string CNodeCounterLog::getTypeName(const cocos2d::CCObject* _node) const
{
    std::string typName(typeid(*_node).name());
    short lastpos = typName.find_last_of(gCocosNS); //干掉前缀class coocs2d::
    if (lastpos == std::string::npos)
    {
        assert(false,"--------- typName is not cocos2d::");
        return typName;
    }
    return  typName.substr(lastpos + 1,typName.length() - lastpos - 1);;
}

void CNodeCounterLog::log(const std::string& _str /* = "" */)
{
    std::ofstream osOutFile(logFile.c_str(),std::ios::app);
    if (!osOutFile.is_open())
    {
        osOutFile.close();
        assert(false,"--- Error: write file error");
        return;
    }
    osOutFile << _str;
    osOutFile.close();
}

void CNodeCounterLog::visit()
{
    std::string info("");
    std::string info2("");
    getInfo(info,info2);
    if (mParentNode && mLabelInfo && mLabelInfo2) 
    {
        mLabelInfo->setString(info.c_str());
        mLabelInfo2->setString(info2.c_str());
        mParentNode->visit();
    }
    else
        assert(false,"--- Error: display node null");
}

void CNodeCounterLog::getInfo(string& _info,std::string& _info2) 
{
    std::string allInfo("");
    std::string allInfo2("\n");
    unsigned int totalNum = 0;
    unsigned int totalSize = 0;
    int flag = 0;
    float totalMem = 0.f;

    std::string labelTextureInfo("");
    for (StrNodeMap::const_iterator iter = mNodeMap.begin(); iter != mNodeMap.end(); ++iter)
    {
        //cclabel纹理信息
        getCCLabelTextureInfo(labelTextureInfo,iter->second,totalMem);

        totalNum += iter->second->mCounter;
        totalSize += iter->second->mTotalSize;
        char tmp[128] = { 0 };
        sprintf(tmp,gLogFormat.c_str(),iter->second->mCounter,(float)iter->second->mTotalSize/1024.f,iter->second->mName.c_str());
        if (flag < gChangeLine) // 挂在另一个节点显示
            allInfo.append(tmp);
        else
            allInfo2.append(tmp);
        flag++;
    }

    //纹理信息
    std::string textureInfo("");
    getTextureInfo(textureInfo,totalMem);

    //lua大小
    std::string luaInfo("");
    getLuaInfo(luaInfo,totalMem);

    //json缓存大小
    std::string jsonInfo("");
    getJsonInfo(jsonInfo,totalMem);

    char tmp1[128] = { 0 };
    char tmp2[128] = { 0 };
    float totalMb = (float)(totalSize / 1024) / 1024.f;
    totalMem += totalMb;

    sprintf(tmp1,gLogTotalMemSize.c_str(),totalMem);
    sprintf(tmp2,gLogFormatTexture.c_str(),totalNum,totalMb,"CCNodes");

    _info.append(tmp1); //total
    _info.append(textureInfo);
    _info.append(labelTextureInfo);
    _info.append(luaInfo);
    _info.append(jsonInfo);
    _info.append(tmp2); //total

    if (mShowAll)
    {
        _info.append("----------- split -----------\n");
        _info.append(allInfo);
        _info2.append(allInfo2);
    }
}

void CNodeCounterLog::getTextureInfo(std::string& _info,float& _size)
{
    CCDictionary* textures = CCTextureCache::sharedTextureCache()->getAllTextures();
    unsigned int counter = 0;
    unsigned int totalBytes = 0;

    CCDictElement* pElement = NULL;
    CCDICT_FOREACH(textures,pElement)
    {
        CCTexture2D* tex = (CCTexture2D*)pElement->getObject();
        unsigned int bpp = tex->bitsPerPixelForFormat();
        unsigned int bytes = tex->getPixelsWide() * tex->getPixelsHigh() * bpp / 8;
        totalBytes += bytes;
        counter++;
    }

    if (totalBytes > 0)
    {
        float totalMb = (float)(totalBytes / 1024) / 1024.f;
        _size += totalMb;
        char tmp[128] = { 0 };
        sprintf(tmp,counter,CC_Texture2D);

        //if (totalMb > 150.f)
        // CCTextureCache::sharedTextureCache()->removeUnusedTextures();

        _info.append(tmp);
    }
}

void CNodeCounterLog::getCCLabelTextureInfo(std::string& _info,float& _size)
{
    if (strcmp(_nodeInfo->mName.c_str(),CC_LabelTTF) != 0)
        return;

    unsigned int totalBytes = 0;
    for (std::vector<CCObject*>::const_iterator iter = _nodeInfo->mPtrVec.begin(); iter != _nodeInfo->mPtrVec.end(); ++iter)
    {
        CCLabelTTF* label = dynamic_cast<CCLabelTTF*>(*iter);
        if (label)
        {
            CCTexture2D* tex = label->getTexture();
            unsigned int bpp = tex->bitsPerPixelForFormat();
            if (bpp != -1)
            {
                unsigned int bytes = tex->getPixelsWide() * tex->getPixelsHigh() * bpp / 8;
                totalBytes += bytes;
            }
            else
            {
                int a = 1;
            }
        }
    }

    if (totalBytes > 0)
    {
        float totalMb = (float)(totalBytes / 1024) / 1024.f;
        _size += totalMb;
        char tmp[128] = { 0 };
        sprintf(tmp,_nodeInfo->mPtrVec.size(),CC_LabelTTF);

        /*if (totalMb > 150.f) //缓存纹理超过150自动清除unusedTex CCTextureCache::sharedTextureCache()->removeUnusedTextures();*/

        _info.append(tmp);
    }
}

void CNodeCounterLog::getLuaInfo(std::string& _info,float& _size)
{
    int size = CCLuaEngine::defaultEngine()->getMemSize();
    if (size > 0)
    {
        char tmp[128] = { 0 };
        float totalMb = (float)size / 1024.f;
        _size += totalMb;
        sprintf(tmp,1,CC_LuaStack);
        _info.append(tmp);
    }
}

void CNodeCounterLog::getJsonInfo(std::string& _info,float& _size)
{
    unsigned int totoal = 0;
    int num = 0;
    std::map<std::string,rapidjson::Document *>* jsonMap = GUIReader::shareReader()->getJsonCache();
    if (jsonMap)
    {
        for (std::map<std::string,rapidjson::Document *>::iterator iter = jsonMap->begin(); iter != jsonMap->end(); ++iter)
        {
            totoal += iter->second->sizeTmp;
            num += 1;
        }
    }

    if (totoal > 0)
    {
        char tmp[128] = { 0 };
        float totalMb = (float)(totoal / 1024) / 1024.f;
        _size += totalMb;
        sprintf(tmp,num,"JsonCache");
        _info.append(tmp);
    }
}

猜你在找的Cocos2d-x相关文章