diff --git a/build/cocos2d_tests.xcodeproj/project.pbxproj b/build/cocos2d_tests.xcodeproj/project.pbxproj index ff3c35b1fc..4cf287db50 100644 --- a/build/cocos2d_tests.xcodeproj/project.pbxproj +++ b/build/cocos2d_tests.xcodeproj/project.pbxproj @@ -1022,6 +1022,8 @@ FA94B24F1B93EF7B0074B261 /* Images in Resources */ = {isa = PBXBuildFile; fileRef = FA94B24D1B93EF7B0074B261 /* Images */; }; FADE786B1B942DE30061590D /* fonts in Resources */ = {isa = PBXBuildFile; fileRef = FADE786A1B942DE30061590D /* fonts */; }; FADE786C1B942DE30061590D /* fonts in Resources */ = {isa = PBXBuildFile; fileRef = FADE786A1B942DE30061590D /* fonts */; }; + FADE786F1B9451540061590D /* PerformanceNodeChildrenTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADE786D1B9451540061590D /* PerformanceNodeChildrenTest.cpp */; }; + FADE78701B9451540061590D /* PerformanceNodeChildrenTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADE786D1B9451540061590D /* PerformanceNodeChildrenTest.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -2146,6 +2148,8 @@ FA94B24A1B9059540074B261 /* VisibleRect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VisibleRect.h; sourceTree = ""; }; FA94B24D1B93EF7B0074B261 /* Images */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Images; path = "../tests/performance-tests/Resources/Images"; sourceTree = ""; }; FADE786A1B942DE30061590D /* fonts */ = {isa = PBXFileReference; lastKnownFileType = folder; name = fonts; path = "../tests/performance-tests/Resources/fonts"; sourceTree = ""; }; + FADE786D1B9451540061590D /* PerformanceNodeChildrenTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PerformanceNodeChildrenTest.cpp; sourceTree = ""; }; + FADE786E1B9451540061590D /* PerformanceNodeChildrenTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PerformanceNodeChildrenTest.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -4753,6 +4757,8 @@ FA94B2411B90497E0074B261 /* testBasic.h */, FA94B2381B9045160074B261 /* PerformanceAllocTest.cpp */, FA94B2391B9045160074B261 /* PerformanceAllocTest.h */, + FADE786D1B9451540061590D /* PerformanceNodeChildrenTest.cpp */, + FADE786E1B9451540061590D /* PerformanceNodeChildrenTest.h */, ); path = tests; sourceTree = ""; @@ -6229,6 +6235,7 @@ FA94B23B1B9045160074B261 /* PerformanceAllocTest.cpp in Sources */, FA94B1ED1B8EF8250074B261 /* AppController.mm in Sources */, FA94B24C1B9059540074B261 /* VisibleRect.cpp in Sources */, + FADE78701B9451540061590D /* PerformanceNodeChildrenTest.cpp in Sources */, FA94B2361B8F02880074B261 /* Profile.cpp in Sources */, FA94B2021B8EF8250074B261 /* RootViewController.mm in Sources */, FA94B2011B8EF8250074B261 /* main.m in Sources */, @@ -6241,6 +6248,7 @@ buildActionMask = 2147483647; files = ( FA94B2421B90497E0074B261 /* BaseTest.cpp in Sources */, + FADE786F1B9451540061590D /* PerformanceNodeChildrenTest.cpp in Sources */, FA94B2351B8F02880074B261 /* Profile.cpp in Sources */, FA94B1CE1B8EF7BB0074B261 /* AppDelegate.cpp in Sources */, FA94B24B1B9059540074B261 /* VisibleRect.cpp in Sources */, diff --git a/tests/performance-tests/Classes/tests/PerformanceNodeChildrenTest.cpp b/tests/performance-tests/Classes/tests/PerformanceNodeChildrenTest.cpp new file mode 100644 index 0000000000..c7f1f4c451 --- /dev/null +++ b/tests/performance-tests/Classes/tests/PerformanceNodeChildrenTest.cpp @@ -0,0 +1,982 @@ +#include "PerformanceNodeChildrenTest.h" +#include "Profile.h" +#include + +USING_NS_CC; + +// Enable profiles for this file +#undef CC_PROFILER_DISPLAY_TIMERS +#define CC_PROFILER_DISPLAY_TIMERS() Profiler::getInstance()->displayTimers() +#undef CC_PROFILER_PURGE_ALL +#define CC_PROFILER_PURGE_ALL() Profiler::getInstance()->releaseAllTimers() + +#undef CC_PROFILER_START +#define CC_PROFILER_START(__name__) ProfilingBeginTimingBlock(__name__) +#undef CC_PROFILER_STOP +#define CC_PROFILER_STOP(__name__) ProfilingEndTimingBlock(__name__) +#undef CC_PROFILER_RESET +#define CC_PROFILER_RESET(__name__) ProfilingResetTimingBlock(__name__) + +#undef CC_PROFILER_START_CATEGORY +#define CC_PROFILER_START_CATEGORY(__cat__, __name__) do{ if(__cat__) ProfilingBeginTimingBlock(__name__); } while(0) +#undef CC_PROFILER_STOP_CATEGORY +#define CC_PROFILER_STOP_CATEGORY(__cat__, __name__) do{ if(__cat__) ProfilingEndTimingBlock(__name__); } while(0) +#undef CC_PROFILER_RESET_CATEGORY +#define CC_PROFILER_RESET_CATEGORY(__cat__, __name__) do{ if(__cat__) ProfilingResetTimingBlock(__name__); } while(0) + +#undef CC_PROFILER_START_INSTANCE +#define CC_PROFILER_START_INSTANCE(__id__, __name__) do{ ProfilingBeginTimingBlock( String::createWithFormat("%08X - %s", __id__, __name__)->getCString() ); } while(0) +#undef CC_PROFILER_STOP_INSTANCE +#define CC_PROFILER_STOP_INSTANCE(__id__, __name__) do{ ProfilingEndTimingBlock( String::createWithFormat("%08X - %s", __id__, __name__)->getCString() ); } while(0) +#undef CC_PROFILER_RESET_INSTANCE +#define CC_PROFILER_RESET_INSTANCE(__id__, __name__) do{ ProfilingResetTimingBlock( String::createWithFormat("%08X - %s", __id__, __name__)->getCString() ); } while(0) + +PerformceNodeChildrenTests::PerformceNodeChildrenTests() +{ +// ADD_TEST_CASE(IterateSpriteSheetForLoop); +// ADD_TEST_CASE(IterateSpriteSheetIterator); +// ADD_TEST_CASE(IterateSpriteSheetForEach); +// ADD_TEST_CASE(CallFuncsSpriteSheetForEach); + ADD_TEST_CASE(AddSprite); +// ADD_TEST_CASE(AddSpriteSheet); + ADD_TEST_CASE(GetSpriteSheet); + ADD_TEST_CASE(RemoveSprite); +// ADD_TEST_CASE(RemoveSpriteSheet); +// ADD_TEST_CASE(ReorderSpriteSheet); +// ADD_TEST_CASE(SortAllChildrenSpriteSheet); + ADD_TEST_CASE(VisitSceneGraph); +} + +enum { + kTagInfoLayer = 1, + + kTagBase = 20000, +}; + +enum { + kMaxNodes = 15000, + kNodesIncrease = 500, +}; + +int NodeChildrenMainScene::quantityOfNodes = kNodesIncrease; + +static int autoTestNodesNums[] = { + 1000, 2000, 3000 +}; + +//////////////////////////////////////////////////////// +// +// NodeChildrenMainScene +// +//////////////////////////////////////////////////////// +NodeChildrenMainScene::NodeChildrenMainScene() +: autoTestIndex(0) +{ + +} + +bool NodeChildrenMainScene::init() +{ + if (TestCase::init()) + { + initWithQuantityOfNodes(quantityOfNodes); + return true; + } + + return false; +} + +void NodeChildrenMainScene::onExitTransitionDidStart() +{ + auto director = Director::getInstance(); + auto sched = director->getScheduler(); + + sched->unschedule(CC_SCHEDULE_SELECTOR(NodeChildrenMainScene::dumpProfilerInfo), this); +} + +void NodeChildrenMainScene::onEnterTransitionDidFinish() +{ + auto director = Director::getInstance(); + auto sched = director->getScheduler(); + + if (this->isAutoTesting()) { + // Update the quantity of nodes if is auto testing. + quantityOfNodes = autoTestNodesNums[autoTestIndex]; + updateQuantityLabel(); + updateQuantityOfNodes(); + updateProfilerName(); + + Profile::getInstance()->testCaseBegin(getTestCaseName(), + genStrVector("NodeCount", nullptr), + genStrVector("Avg", "Min", "Max", nullptr)); + } + + CC_PROFILER_PURGE_ALL(); + sched->schedule(CC_SCHEDULE_SELECTOR(NodeChildrenMainScene::dumpProfilerInfo), this, 2, false); +} + +void NodeChildrenMainScene::dumpProfilerInfo(float dt) +{ + CC_PROFILER_DISPLAY_TIMERS(); + + if (this->isAutoTesting()) { + // record the test result to class Profile + auto timer = Profiler::getInstance()->_activeTimers.at(_profilerName); + auto numStr = genStr("%d", quantityOfNodes); + auto avgStr = genStr("%ldµ", timer->_averageTime2); + auto minStr = genStr("%ldµ", timer->minTime); + auto maxStr = genStr("%ldµ", timer->maxTime); + Profile::getInstance()->addTestResult(genStrVector(numStr.c_str(), nullptr), + genStrVector(avgStr.c_str(), minStr.c_str(), maxStr.c_str(), nullptr)); + + auto testsSize = sizeof(autoTestNodesNums)/sizeof(int); + if (autoTestIndex >= (testsSize - 1)) { + // if it's the last one of auto test. End the auto test. + this->setAutoTesting(false); + Profile::getInstance()->testCaseEnd(); + } + else + { + // update the auto test index + autoTestIndex++; + quantityOfNodes = autoTestNodesNums[autoTestIndex]; + updateQuantityLabel(); + updateQuantityOfNodes(); + updateProfilerName(); + CC_PROFILER_PURGE_ALL(); + } + } +} + +void NodeChildrenMainScene::initWithQuantityOfNodes(unsigned int nNodes) +{ + //srand(time()); + auto s = Director::getInstance()->getWinSize(); + + lastRenderedCount = 0; + currentQuantityOfNodes = 0; + quantityOfNodes = nNodes; + + MenuItemFont::setFontSize(65); + auto decrease = MenuItemFont::create(" - ", [&](Ref *sender) { + quantityOfNodes -= kNodesIncrease; + if( quantityOfNodes < 0 ) + quantityOfNodes = 0; + + updateQuantityLabel(); + updateQuantityOfNodes(); + updateProfilerName(); + CC_PROFILER_PURGE_ALL(); + srand(0); + }); + decrease->setColor(Color3B(0,200,20)); + auto increase = MenuItemFont::create(" + ", [&](Ref *sender) { + quantityOfNodes += kNodesIncrease; + if( quantityOfNodes > kMaxNodes ) + quantityOfNodes = kMaxNodes; + + updateQuantityLabel(); + updateQuantityOfNodes(); + updateProfilerName(); + CC_PROFILER_PURGE_ALL(); + srand(0); + }); + increase->setColor(Color3B(0,200,20)); + + auto menu = Menu::create(decrease, increase, nullptr); + menu->alignItemsHorizontally(); + menu->setPosition(Vec2(s.width/2, s.height/2+15)); + addChild(menu, 1); + + auto infoLabel = Label::createWithTTF("0 nodes", "fonts/Marker Felt.ttf", 30); + infoLabel->setColor(Color3B(0,200,20)); + infoLabel->setPosition(Vec2(s.width/2, s.height/2-15)); + addChild(infoLabel, 1, kTagInfoLayer); + + updateQuantityLabel(); + updateQuantityOfNodes(); + updateProfilerName(); + srand(0); +} + +std::string NodeChildrenMainScene::title() const +{ + return "No title"; +} + +std::string NodeChildrenMainScene::subtitle() const +{ + return ""; +} + +void NodeChildrenMainScene::updateQuantityLabel() +{ + if( quantityOfNodes != lastRenderedCount ) + { + auto infoLabel = static_cast( getChildByTag(kTagInfoLayer) ); + char str[20] = {0}; + sprintf(str, "%u nodes", quantityOfNodes); + infoLabel->setString(str); + + lastRenderedCount = quantityOfNodes; + } +} + +const char * NodeChildrenMainScene::profilerName() +{ + return _profilerName; +} + +void NodeChildrenMainScene::updateProfilerName() +{ + snprintf(_profilerName, sizeof(_profilerName)-1, "%s(%d)", testName(), quantityOfNodes); +} + + +//////////////////////////////////////////////////////// +// +// IterateSpriteSheet +// +//////////////////////////////////////////////////////// +IterateSpriteSheet::~IterateSpriteSheet() +{ + +} + +void IterateSpriteSheet::updateQuantityOfNodes() +{ + // increase nodes + if( currentQuantityOfNodes < quantityOfNodes ) + { + for(int i = 0; i < (quantityOfNodes-currentQuantityOfNodes); i++) + { + auto sprite = Sprite::createWithTexture(batchNode->getTexture(), Rect(0, 0, 32, 32)); + batchNode->addChild(sprite); + sprite->setVisible(false); + sprite->setPosition(Vec2(-1000,-1000)); + } + } + + // decrease nodes + else if ( currentQuantityOfNodes > quantityOfNodes ) + { + for(int i = 0; i < (currentQuantityOfNodes-quantityOfNodes); i++) + { + int index = currentQuantityOfNodes-i-1; + batchNode->removeChildAtIndex(index, true); + } + } + + currentQuantityOfNodes = quantityOfNodes; +} + +void IterateSpriteSheet::initWithQuantityOfNodes(unsigned int nNodes) +{ + batchNode = SpriteBatchNode::create("Images/spritesheet1.png"); + addChild(batchNode); + + NodeChildrenMainScene::initWithQuantityOfNodes(nNodes); + + scheduleUpdate(); +} + +const char* IterateSpriteSheet::testName() +{ + return "none"; +} + +//////////////////////////////////////////////////////// +// +// IterateSpriteSheetForLoop +// +//////////////////////////////////////////////////////// +void IterateSpriteSheetForLoop::update(float dt) +{ + // iterate using fast enumeration protocol + auto& children = batchNode->getChildren(); + + CC_PROFILER_START(this->profilerName()); + + for( const auto &object : children ) + { + auto o = static_cast(object); + auto sprite = static_cast(o); + sprite->setVisible(false); + } + + CC_PROFILER_STOP(this->profilerName()); +} + +std::string IterateSpriteSheetForLoop::title() const +{ + return "Iterate SpriteSheet"; +} + +std::string IterateSpriteSheetForLoop::subtitle() const +{ + return "Iterate children using C++11 range-based for loop. See console"; +} + +const char* IterateSpriteSheetForLoop::testName() +{ + return "Iterator: C++11 for loop"; +} + + +//////////////////////////////////////////////////////// +// +// IterateSpriteSheetIterator +// +//////////////////////////////////////////////////////// +void IterateSpriteSheetIterator::update(float dt) +{ + // iterate using fast enumeration protocol + auto& children = batchNode->getChildren(); + + CC_PROFILER_START(this->profilerName()); + + for( auto it=std::begin(children); it != std::end(children); ++it) + { + auto sprite = static_cast(*it); + sprite->setVisible(false); + } + + CC_PROFILER_STOP(this->profilerName()); +} + + +std::string IterateSpriteSheetIterator::title() const +{ + return "Iterate SpriteSheet"; +} + +std::string IterateSpriteSheetIterator::subtitle() const +{ + return "Iterate children using begin() / end(). See console"; +} + +const char* IterateSpriteSheetIterator::testName() +{ + return "Iterator: begin(), end()"; +} + +//////////////////////////////////////////////////////// +// +// IterateSpriteSheetForEach +// +//////////////////////////////////////////////////////// +void IterateSpriteSheetForEach::update(float dt) +{ + // iterate using fast enumeration protocol + auto& children = batchNode->getChildren(); + + CC_PROFILER_START(this->profilerName()); + + std::for_each(std::begin(children), std::end(children), [](Node *child) { + auto sprite = static_cast(child); + sprite->setVisible(false); + }); + + CC_PROFILER_STOP(this->profilerName()); +} + + +std::string IterateSpriteSheetForEach::title() const +{ + return "Iterate SpriteSheet"; +} + +std::string IterateSpriteSheetForEach::subtitle() const +{ + return "Iterate children using std::for_each(). See console"; +} + +const char* IterateSpriteSheetForEach::testName() +{ + return "Iterator: std::for_each()"; +} + + +//////////////////////////////////////////////////////// +// +// CallFuncsSpriteSheetForEach +// +//////////////////////////////////////////////////////// +void CallFuncsSpriteSheetForEach::update(float dt) +{ + // iterate using fast enumeration protocol + auto& children = batchNode->getChildren(); + + CC_PROFILER_START(this->profilerName()); + + std::for_each(std::begin(children), std::end(children), [](Node* obj) { + obj->getPosition(); + }); + + CC_PROFILER_STOP(this->profilerName()); +} + + +std::string CallFuncsSpriteSheetForEach::title() const +{ + return "'map' functional call"; +} + +std::string CallFuncsSpriteSheetForEach::subtitle() const +{ + return "Using 'std::for_each()'. See console"; +} + +const char* CallFuncsSpriteSheetForEach::testName() +{ + return "Map: std::for_each"; +} + +//////////////////////////////////////////////////////// +// +// AddRemoveSpriteSheet +// +//////////////////////////////////////////////////////// +AddRemoveSpriteSheet::~AddRemoveSpriteSheet() +{ + +} + +void AddRemoveSpriteSheet::initWithQuantityOfNodes(unsigned int nNodes) +{ + batchNode = SpriteBatchNode::create("Images/spritesheet1.png"); + addChild(batchNode); + + NodeChildrenMainScene::initWithQuantityOfNodes(nNodes); + + scheduleUpdate(); +} + +void AddRemoveSpriteSheet::updateQuantityOfNodes() +{ + auto s = Director::getInstance()->getWinSize(); + + // increase nodes + if( currentQuantityOfNodes < quantityOfNodes ) + { + for (int i=0; i < (quantityOfNodes-currentQuantityOfNodes); i++) + { + auto sprite = Sprite::createWithTexture(batchNode->getTexture(), Rect(0, 0, 32, 32)); + batchNode->addChild(sprite); + sprite->setPosition(Vec2( CCRANDOM_0_1()*s.width, CCRANDOM_0_1()*s.height)); + sprite->setVisible(false); + } + } + // decrease nodes + else if ( currentQuantityOfNodes > quantityOfNodes ) + { + for(int i=0;i < (currentQuantityOfNodes-quantityOfNodes);i++) + { + int index = currentQuantityOfNodes-i-1; + batchNode->removeChildAtIndex(index, true); + } + } + + currentQuantityOfNodes = quantityOfNodes; +} + +const char* AddRemoveSpriteSheet::testName() +{ + return "none"; +} + +//////////////////////////////////////////////////////// +// +// AddSprite +// +//////////////////////////////////////////////////////// +void AddSprite::update(float dt) +{ + // reset seed + //srandom(0); + + // 100 percent + int totalToAdd = currentQuantityOfNodes * 1; + + if( totalToAdd > 0 ) + { + Sprite **sprites = new (std::nothrow) Sprite*[totalToAdd]; + int *zs = new int[totalToAdd]; + + // Don't include the sprite creation time and random as part of the profiling + for(int i=0; igetTexture(), Rect(0,0,32,32)); + zs[i] = CCRANDOM_MINUS1_1() * 50; + } + + // add them with random Z (very important!) + CC_PROFILER_START( this->profilerName() ); + + for( int i=0; i < totalToAdd;i++ ) + { + this->addChild( sprites[i], zs[i], kTagBase+i); + } + CC_PROFILER_STOP(this->profilerName()); + + + batchNode->sortAllChildren(); + + // remove them + for( int i=0;i < totalToAdd;i++) + { + this->removeChild( sprites[i], true); + } + + delete [] sprites; + delete [] zs; + } +} + +std::string AddSprite::title() const +{ + return "Node::addChild()"; +} + +std::string AddSprite::subtitle() const +{ + return "Adds sprites with random z. See console"; +} + +const char* AddSprite::testName() +{ + return "Node::addChild()"; +} + +//////////////////////////////////////////////////////// +// +// AddSpriteSheet +// +//////////////////////////////////////////////////////// +void AddSpriteSheet::update(float dt) +{ + // reset seed + //srandom(0); + + // 100 percent + int totalToAdd = currentQuantityOfNodes * 1; + + if( totalToAdd > 0 ) + { + Sprite **sprites = new (std::nothrow) Sprite*[totalToAdd]; + int *zs = new int[totalToAdd]; + + // Don't include the sprite creation time and random as part of the profiling + for(int i=0; igetTexture(), Rect(0,0,32,32)); + zs[i] = CCRANDOM_MINUS1_1() * 50; + } + + // add them with random Z (very important!) + CC_PROFILER_START( this->profilerName() ); + + for( int i=0; i < totalToAdd;i++ ) + { + batchNode->addChild( sprites[i], zs[i], kTagBase+i); + } + CC_PROFILER_STOP(this->profilerName()); + + + batchNode->sortAllChildren(); + + // remove them + for( int i=0;i < totalToAdd;i++) + { + batchNode->removeChild( sprites[i], true); + } + + delete [] sprites; + delete [] zs; + } +} + +std::string AddSpriteSheet::title() const +{ + return "SpriteBatchNode::addChild()"; +} + +std::string AddSpriteSheet::subtitle() const +{ + return "Adds sprites with random z. See console"; +} + +const char* AddSpriteSheet::testName() +{ + return "SpriteBatchNode::addChild()"; +} + +//////////////////////////////////////////////////////// +// +// GetSpriteSheet +// +//////////////////////////////////////////////////////// +void GetSpriteSheet::update(float dt) +{ + // reset seed + //srandom(0); + + // 100% percent + int totalToAdd = currentQuantityOfNodes * 1; + + if( totalToAdd > 0 ) + { + Sprite **sprites = new (std::nothrow) Sprite*[totalToAdd]; + int *zs = new int[totalToAdd]; + + // Don't include the sprite creation time and random as part of the profiling + for(int i=0; igetTexture(), Rect(0,0,32,32)); + zs[i] = CCRANDOM_MINUS1_1() * 50; + } + + for( int i=0; i < totalToAdd;i++ ) + { + batchNode->addChild( sprites[i], zs[i], kTagBase+i); + } + + batchNode->sortAllChildren(); + + CC_PROFILER_START( this->profilerName() ); + for( int i=0; i < totalToAdd;i++ ) + { + batchNode->getChildByTag(kTagBase+1); + } + CC_PROFILER_STOP(this->profilerName()); + + // remove them + for( int i=0;i < totalToAdd;i++) + { + batchNode->removeChild( sprites[i], true); + } + + delete [] sprites; + delete [] zs; + } +} + +std::string GetSpriteSheet::title() const +{ + return "getChildByTag from spritesheet"; +} + +std::string GetSpriteSheet::subtitle() const +{ + return "Get sprites using getChildByTag(). See console"; +} + +const char* GetSpriteSheet::testName() +{ + return "SpriteBatchNode::getChildByTag()"; +} + + +//////////////////////////////////////////////////////// +// +// RemoveSprite +// +//////////////////////////////////////////////////////// +void RemoveSprite::update(float dt) +{ + //srandom(0); + + // 100 percent + int totalToAdd = currentQuantityOfNodes * 1; + + if( totalToAdd > 0 ) + { + Sprite **sprites = new (std::nothrow) Sprite*[totalToAdd]; + + // Don't include the sprite creation time as part of the profiling + for(int i=0;igetTexture(), Rect(0,0,32,32)); + } + + // add them with random Z (very important!) + for( int i=0; i < totalToAdd;i++ ) + { + this->addChild( sprites[i], CCRANDOM_MINUS1_1() * 50, kTagBase+i); + } + + // remove them + CC_PROFILER_START( this->profilerName() ); + for( int i=0;i < totalToAdd;i++) + { + this->removeChild( sprites[i], true); + } + CC_PROFILER_STOP( this->profilerName() ); + + delete [] sprites; + } +} + +std::string RemoveSprite::title() const +{ + return "Node::removeChild()"; +} + +std::string RemoveSprite::subtitle() const +{ + return "Remove sprites. See console"; +} + +const char* RemoveSprite::testName() +{ + return "Node::removeChild()"; +} + +//////////////////////////////////////////////////////// +// +// RemoveSpriteSheet +// +//////////////////////////////////////////////////////// +void RemoveSpriteSheet::update(float dt) +{ + //srandom(0); + + // 100 percent + int totalToAdd = currentQuantityOfNodes * 1; + + if( totalToAdd > 0 ) + { + Sprite **sprites = new (std::nothrow) Sprite*[totalToAdd]; + + // Don't include the sprite creation time as part of the profiling + for(int i=0;igetTexture(), Rect(0,0,32,32)); + } + + // add them with random Z (very important!) + for( int i=0; i < totalToAdd;i++ ) + { + batchNode->addChild( sprites[i], CCRANDOM_MINUS1_1() * 50, kTagBase+i); + } + + // remove them + CC_PROFILER_START( this->profilerName() ); + for( int i=0;i < totalToAdd;i++) + { + batchNode->removeChild( sprites[i], true); + } + CC_PROFILER_STOP( this->profilerName() ); + + delete [] sprites; + } +} + +std::string RemoveSpriteSheet::title() const +{ + return "SpriteBatchNode::removeChild()"; +} + +std::string RemoveSpriteSheet::subtitle() const +{ + return "Remove sprites. See console"; +} + +const char* RemoveSpriteSheet::testName() +{ + return "SpriteBatchNode::removeChild()"; +} + +//////////////////////////////////////////////////////// +// +// ReorderSpriteSheet +// +//////////////////////////////////////////////////////// +void ReorderSpriteSheet::update(float dt) +{ + //srandom(0); + + // 100 percent + int totalToAdd = currentQuantityOfNodes * 1; + + if( totalToAdd > 0 ) + { + Sprite **sprites = new (std::nothrow) Sprite*[totalToAdd]; + + // Don't include the sprite creation time as part of the profiling + for(int i=0; igetTexture(), Rect(0,0,32,32)); + } + + // add them with random Z (very important!) + for( int i=0; i < totalToAdd;i++ ) + { + batchNode->addChild( sprites[i], CCRANDOM_MINUS1_1() * 50, kTagBase+i); + } + + batchNode->sortAllChildren(); + + // reorder them + CC_PROFILER_START( this->profilerName() ); + for( int i=0;i < totalToAdd;i++) + { + batchNode->reorderChild(sprites[i], CCRANDOM_MINUS1_1() * 50); + } + CC_PROFILER_STOP( this->profilerName() ); + + // remove them + for( int i=0;i < totalToAdd;i++) + { + batchNode->removeChild( sprites[i], true); + } + + delete [] sprites; + } +} + +std::string ReorderSpriteSheet::title() const +{ + return "SpriteBatchNode::reorderChild()"; +} + +std::string ReorderSpriteSheet::subtitle() const +{ + return "Reorder sprites. See console"; +} + +const char* ReorderSpriteSheet::testName() +{ + return "SpriteBatchNode::reorderChild()"; +} + +//////////////////////////////////////////////////////// +// +// SortAllChildrenSpriteSheet +// +//////////////////////////////////////////////////////// +void SortAllChildrenSpriteSheet::update(float dt) +{ + //srandom(0); + + // 100 percent + int totalToAdd = currentQuantityOfNodes * 1; + + if( totalToAdd > 0 ) + { + Sprite **sprites = new (std::nothrow) Sprite*[totalToAdd]; + + // Don't include the sprite's creation time as part of the profiling + for(int i=0; igetTexture(), Rect(0,0,32,32)); + } + + // add them with random Z (very important!) + for( int i=0; i < totalToAdd;i++ ) + { + batchNode->addChild( sprites[i], CCRANDOM_MINUS1_1() * 50, kTagBase+i); + } + + batchNode->sortAllChildren(); + + // reorder them + for( int i=0;i < totalToAdd;i++) + { + batchNode->reorderChild(sprites[i], CCRANDOM_MINUS1_1() * 50); + } + + CC_PROFILER_START( this->profilerName() ); + batchNode->sortAllChildren(); + CC_PROFILER_STOP( this->profilerName() ); + + // remove them + for( int i=0;i < totalToAdd;i++) + { + batchNode->removeChild( sprites[i], true); + } + + delete [] sprites; + } +} + +std::string SortAllChildrenSpriteSheet::title() const +{ + return "SpriteBatchNode::sortAllChildren()"; +} + +std::string SortAllChildrenSpriteSheet::subtitle() const +{ + return "Calls sortOfChildren(). See console"; +} + +const char* SortAllChildrenSpriteSheet::testName() +{ + return "SpriteBatchNode::sortAllChildren()"; +} + + +//////////////////////////////////////////////////////// +// +// VisitSceneGraph +// +//////////////////////////////////////////////////////// +void VisitSceneGraph::initWithQuantityOfNodes(unsigned int nodes) +{ + NodeChildrenMainScene::initWithQuantityOfNodes(nodes); + scheduleUpdate(); +} + +void VisitSceneGraph::updateQuantityOfNodes() +{ + auto s = Director::getInstance()->getWinSize(); + + // increase nodes + if( currentQuantityOfNodes < quantityOfNodes ) + { + for(int i = 0; i < (quantityOfNodes-currentQuantityOfNodes); i++) + { + auto node = Node::create(); + this->addChild(node); + node->setVisible(true); + node->setPosition(Vec2(-1000,-1000)); + node->setTag(1000 + currentQuantityOfNodes + i ); + } + } + + // decrease nodes + else if ( currentQuantityOfNodes > quantityOfNodes ) + { + for(int i = 0; i < (currentQuantityOfNodes-quantityOfNodes); i++) + { + this->removeChildByTag(1000 + currentQuantityOfNodes - i -1 ); + } + } + + currentQuantityOfNodes = quantityOfNodes; +} +void VisitSceneGraph::update(float dt) +{ + CC_PROFILER_START( this->profilerName() ); + this->visit(); + CC_PROFILER_STOP( this->profilerName() ); + + // Call `Renderer::clean` to prevent crash if current scene is destroyed. + // The render commands associated with current scene should be cleaned. + Director::getInstance()->getRenderer()->clean(); +} + +std::string VisitSceneGraph::title() const +{ + return "Performance of visiting the scene graph"; +} + +std::string VisitSceneGraph::subtitle() const +{ + return "calls visit() on scene graph. See console"; +} + +const char* VisitSceneGraph::testName() +{ + return "visit()"; +} diff --git a/tests/performance-tests/Classes/tests/PerformanceNodeChildrenTest.h b/tests/performance-tests/Classes/tests/PerformanceNodeChildrenTest.h new file mode 100644 index 0000000000..ed8b6f77c4 --- /dev/null +++ b/tests/performance-tests/Classes/tests/PerformanceNodeChildrenTest.h @@ -0,0 +1,221 @@ +#ifndef __PERFORMANCE_NODE_CHILDREN_TEST_H__ +#define __PERFORMANCE_NODE_CHILDREN_TEST_H__ + +#include "BaseTest.h" + +DEFINE_TEST_SUITE(PerformceNodeChildrenTests); + +class NodeChildrenMainScene : public TestCase +{ +public: + virtual bool init() override; + virtual void initWithQuantityOfNodes(unsigned int nNodes); + virtual std::string title() const override; + virtual std::string subtitle() const override; + virtual void updateQuantityOfNodes() = 0; + + const char* profilerName(); + void updateProfilerName(); + + // for the profiler + virtual const char* testName() = 0; + + void updateQuantityLabel(); + + void dumpProfilerInfo(float dt); + + virtual void onExitTransitionDidStart() override; + virtual void onEnterTransitionDidFinish() override; +protected: + NodeChildrenMainScene(); + static int quantityOfNodes; + char _profilerName[256]; + int lastRenderedCount; + int currentQuantityOfNodes; + int autoTestIndex; +}; + +class IterateSpriteSheet : public NodeChildrenMainScene +{ +public: + virtual ~IterateSpriteSheet(); + virtual void updateQuantityOfNodes(); + virtual void initWithQuantityOfNodes(unsigned int nNodes); + virtual void update(float dt) = 0; + virtual const char* testName(); + +protected: + cocos2d::SpriteBatchNode *batchNode; +}; + +class IterateSpriteSheetForLoop : public IterateSpriteSheet +{ +public: + CREATE_FUNC(IterateSpriteSheetForLoop); + + IterateSpriteSheetForLoop() {} + virtual void update(float dt) override; + + virtual std::string title() const override; + virtual std::string subtitle() const override; + virtual const char* testName() override; +}; + +class IterateSpriteSheetIterator : public IterateSpriteSheet +{ +public: + CREATE_FUNC(IterateSpriteSheetIterator); + + IterateSpriteSheetIterator() {} + virtual void update(float dt) override; + + virtual std::string title() const override; + virtual std::string subtitle() const override; + virtual const char* testName()override; +}; + +class IterateSpriteSheetForEach : public IterateSpriteSheet +{ +public: + CREATE_FUNC(IterateSpriteSheetForEach); + + virtual void update(float dt) override; + + virtual std::string title() const override; + virtual std::string subtitle() const override; + virtual const char* testName()override; +}; + + +class AddRemoveSpriteSheet : public NodeChildrenMainScene +{ +public: + virtual ~AddRemoveSpriteSheet(); + virtual void updateQuantityOfNodes()override; + virtual void initWithQuantityOfNodes(unsigned int nNodes)override; + virtual void update(float dt)override = 0 ; + virtual const char* testName()override; + +protected: + cocos2d::SpriteBatchNode *batchNode; + +#if CC_ENABLE_PROFILERS + ProfilingTimer* _profilingTimer; +#endif +}; + +/// + +class CallFuncsSpriteSheetForEach : public IterateSpriteSheet +{ +public: + CREATE_FUNC(CallFuncsSpriteSheetForEach); + + virtual void update(float dt) override; + + virtual std::string title() const override; + virtual std::string subtitle() const override; + virtual const char* testName()override; +}; + +/// + +class AddSprite : public AddRemoveSpriteSheet +{ +public: + CREATE_FUNC(AddSprite); + + virtual void update(float dt) override; + + virtual std::string title() const override; + virtual std::string subtitle() const override; + virtual const char* testName()override; +}; + +class AddSpriteSheet : public AddRemoveSpriteSheet +{ +public: + CREATE_FUNC(AddSpriteSheet); + + virtual void update(float dt) override; + + virtual std::string title() const override; + virtual std::string subtitle() const override; + virtual const char* testName()override; +}; + +class GetSpriteSheet : public AddRemoveSpriteSheet +{ +public: + CREATE_FUNC(GetSpriteSheet); + + virtual void update(float dt) override; + + virtual std::string title() const override; + virtual std::string subtitle() const override; + virtual const char* testName()override; +}; + +class RemoveSprite : public AddRemoveSpriteSheet +{ +public: + CREATE_FUNC(RemoveSprite); + + virtual void update(float dt) override; + + virtual std::string title() const override; + virtual std::string subtitle() const override; + virtual const char* testName()override; +}; + +class RemoveSpriteSheet : public AddRemoveSpriteSheet +{ +public: + CREATE_FUNC(RemoveSpriteSheet); + + virtual void update(float dt) override; + + virtual std::string title() const override; + virtual std::string subtitle() const override; + virtual const char* testName()override; +}; + +class ReorderSpriteSheet : public AddRemoveSpriteSheet +{ +public: + CREATE_FUNC(ReorderSpriteSheet); + + virtual void update(float dt) override; + + virtual std::string title() const override; + virtual std::string subtitle() const override; + virtual const char* testName()override; +}; + +class SortAllChildrenSpriteSheet : public AddRemoveSpriteSheet +{ +public: + CREATE_FUNC(SortAllChildrenSpriteSheet); + + virtual void update(float dt) override; + + virtual std::string title() const override; + virtual std::string subtitle() const override; + virtual const char* testName()override; +}; + +class VisitSceneGraph : public NodeChildrenMainScene +{ +public: + CREATE_FUNC(VisitSceneGraph); + + void initWithQuantityOfNodes(unsigned int nodes) override; + + virtual void update(float dt) override; + void updateQuantityOfNodes() override; + virtual std::string title() const override; + virtual std::string subtitle() const override; + virtual const char* testName() override; +}; + +#endif // __PERFORMANCE_NODE_CHILDREN_TEST_H__ diff --git a/tests/performance-tests/Classes/tests/controller.cpp b/tests/performance-tests/Classes/tests/controller.cpp index 6a1d00a1a0..6687c70e46 100644 --- a/tests/performance-tests/Classes/tests/controller.cpp +++ b/tests/performance-tests/Classes/tests/controller.cpp @@ -21,6 +21,7 @@ public: RootTests() { addTest("Alloc Tests", []() { return new PerformceAllocTests(); }); + addTest("Node Children Tests", []() { return new PerformceNodeChildrenTests(); }); } }; diff --git a/tests/performance-tests/Classes/tests/tests.h b/tests/performance-tests/Classes/tests/tests.h index 25d876f1d9..3ddbc1649a 100644 --- a/tests/performance-tests/Classes/tests/tests.h +++ b/tests/performance-tests/Classes/tests/tests.h @@ -3,5 +3,6 @@ // sort them alphabetically. thanks #include "PerformanceAllocTest.h" +#include "PerformanceNodeChildrenTest.h" #endif diff --git a/tests/performance-tests/Resources/Images/spritesheet1.png b/tests/performance-tests/Resources/Images/spritesheet1.png new file mode 100755 index 0000000000..7ab88aaa4e Binary files /dev/null and b/tests/performance-tests/Resources/Images/spritesheet1.png differ