Skip to content

Commit 00f07a5

Browse files
PatriceJiangminggo
authored andcommitted
[v4] add renderer performance test (#20011)
1 parent be0a1db commit 00f07a5

File tree

2 files changed

+331
-25
lines changed

2 files changed

+331
-25
lines changed

tests/cpp-tests/Classes/NewRendererTest/NewRendererTest.cpp

Lines changed: 281 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,46 @@
2424
****************************************************************************/
2525

2626
#include "NewRendererTest.h"
27-
27+
#include <chrono>
28+
#include <sstream>
2829
USING_NS_CC;
2930

31+
class DurationRecorder {
32+
public:
33+
void startTick(const std::string &key) {
34+
_durations[key] = - now();
35+
}
36+
37+
int endTick(const std::string &key) {
38+
auto n = now();
39+
auto itr = _durations.find(key);
40+
if(_durations.find(key) == _durations.end())
41+
{
42+
return -1;
43+
}
44+
else if(itr->second < 0) {
45+
itr->second = n + itr->second;
46+
}
47+
return itr->second;
48+
}
49+
50+
inline int64_t now() const{
51+
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
52+
}
53+
54+
void reset() {
55+
_durations.clear();
56+
}
57+
58+
private:
59+
std::map<std::string, int64_t > _durations;
60+
};
61+
62+
63+
3064
NewRendererTests::NewRendererTests()
3165
{
66+
3267
ADD_TEST_CASE(NewSpriteTest);
3368
ADD_TEST_CASE(GroupCommandTest);
3469
// ADD_TEST_CASE(NewClippingNodeTest); // When depth and stencil are used together, ...
@@ -41,6 +76,7 @@ NewRendererTests::NewRendererTests()
4176
ADD_TEST_CASE(RendererBatchQuadTri);
4277
ADD_TEST_CASE(RendererUniformBatch);
4378
ADD_TEST_CASE(RendererUniformBatch2);
79+
ADD_TEST_CASE(SpriteCreation);
4480
ADD_TEST_CASE(NonBatchSprites);
4581
};
4682

@@ -382,6 +418,167 @@ std::string NewCullingTest::subtitle() const
382418
return "Drag the layer to test the result of culling";
383419
}
384420

421+
SpriteCreation::SpriteCreation()
422+
{
423+
424+
Size s = Director::getInstance()->getWinSize();
425+
Node* parent = Node::create();
426+
parent->setPosition(s.width / 2,s.height / 2);
427+
addChild(parent);
428+
429+
430+
#define KEY_CREATION "11"
431+
#define KEY_DESTROYATION "22"
432+
433+
labelCreate = Label::createWithTTF(TTFConfig("fonts/arial.ttf"), "Sprite Creation: ..");
434+
labelDestory= Label::createWithTTF(TTFConfig("fonts/arial.ttf"), "Destroy Sprites: ..");
435+
436+
MenuItemFont::setFontName("fonts/arial.ttf");
437+
MenuItemFont::setFontSize(65);
438+
auto decrease = MenuItemFont::create(" - ", CC_CALLBACK_1(SpriteCreation::delSpritesCallback, this));
439+
decrease->setColor(Color3B(0, 200, 20));
440+
auto increase = MenuItemFont::create(" + ", CC_CALLBACK_1(SpriteCreation::addSpritesCallback, this));
441+
increase->setColor(Color3B(0, 200, 20));
442+
443+
auto menu = Menu::create(decrease, increase, nullptr);
444+
menu->alignItemsHorizontally();
445+
menu->setPosition(Vec2(s.width / 2, s.height - 105));
446+
addChild(menu, 1);
447+
448+
TTFConfig ttfCount("fonts/Marker Felt.ttf", 30);
449+
_labelSpriteNum = Label::createWithTTF(ttfCount, "Label");
450+
_labelSpriteNum->setColor(Color3B(0, 200, 20));
451+
_labelSpriteNum->setPosition(Vec2(s.width / 2, s.height - 130));
452+
addChild(_labelSpriteNum);
453+
454+
updateSpriteCountLabel(totalSprites);
455+
456+
labelCreate->setPosition(0, -20);
457+
labelDestory->setPosition(0, -50);
458+
459+
parent->addChild(labelCreate);
460+
parent->addChild(labelDestory);
461+
462+
doTest();
463+
}
464+
465+
void SpriteCreation::updateSpriteCountLabel(int x)
466+
{
467+
totalSprites = std::max(1, x);
468+
std::stringstream ss;
469+
ss << totalSprites << " sprites";
470+
_labelSpriteNum->setString(ss.str());
471+
}
472+
473+
void SpriteCreation::doTest()
474+
{
475+
476+
DurationRecorder perf;
477+
std::vector<std::string> predefineTextures = {
478+
"Images/concave.png",
479+
"Images/atlastest.png",
480+
"Images/grossini_dance_atlas-mono.png",
481+
"Images/HelloWorld.png",
482+
"Images/background1.png",
483+
"Images/background2.png",
484+
"Images/stone.png",
485+
"Images/issue_17116.png",
486+
"Images/sprite_polygon_crash.png",
487+
"Images/bitmapFontTest3.png",
488+
"Images/cocos-html5.png",
489+
"Images/Fog.png",
490+
"Images/poly_test_textures.png",
491+
"Images/powered.png",
492+
"Images/bug14017.png",
493+
"Images/test-rgba1.png",
494+
"Images/grossinis_heads.png",
495+
"Images/cocos2dbanner.png"
496+
};
497+
498+
499+
std::vector<Sprite*> spriteCache;
500+
spriteCache.reserve(totalSprites);
501+
502+
perf.startTick(KEY_CREATION);
503+
504+
for (int i=0; i< totalSprites; ++i)
505+
{
506+
auto* sprite = new Sprite();
507+
if(sprite == nullptr )
508+
{
509+
break;
510+
}
511+
if(!sprite->initWithFile(predefineTextures[i % predefineTextures.size()]))
512+
{
513+
delete sprite;
514+
break;
515+
}
516+
spriteCache.push_back(sprite);
517+
}
518+
519+
auto creationDuration = perf.endTick(KEY_CREATION);
520+
perf.startTick(KEY_DESTROYATION);
521+
522+
for (int i=0; i< totalSprites; ++i)
523+
{
524+
spriteCache[i]->release();
525+
}
526+
auto destroyDuration = perf.endTick(KEY_DESTROYATION);
527+
std::stringstream ss;
528+
auto t1_ms = creationDuration * 1.0 / 1000000;
529+
ss << "Create "<< spriteCache.size() << " sprites takes " << t1_ms<< " ms, " << (int64_t)(spriteCache.size() * 1000 / t1_ms) << " sprites per second!";
530+
labelCreate->setString(ss.str());
531+
532+
if(t1_ms < 100) {
533+
suggestDelta =(int) (0.5 * totalSprites);
534+
} else if (t1_ms < 1000) {
535+
suggestDelta =(int) (0.2 * totalSprites);
536+
} else if(t1_ms) {
537+
suggestDelta =(int) (0.1 * totalSprites);
538+
}
539+
540+
suggestDelta = suggestDelta < 1000 ? 1000 : suggestDelta - suggestDelta % 1000;
541+
542+
ss.str("");
543+
auto t2_ms = destroyDuration * 1.0 / 1000000;
544+
ss << "Destroy "<< spriteCache.size() << " sprites takes " << t2_ms<< " ms, " << (int64_t)(spriteCache.size() * 1000 / t2_ms) << " sprites per second!" ;
545+
labelDestory->setString(ss.str());
546+
547+
spriteCache.clear();
548+
}
549+
550+
void SpriteCreation::addSpritesCallback(cocos2d::Ref *)
551+
{
552+
updateSpriteCountLabel(totalSprites + suggestDelta);
553+
doTest();
554+
}
555+
556+
void SpriteCreation::delSpritesCallback(cocos2d::Ref *)
557+
{
558+
updateSpriteCountLabel(totalSprites - suggestDelta);
559+
doTest();
560+
}
561+
562+
SpriteCreation::~SpriteCreation()
563+
{
564+
565+
}
566+
567+
std::string SpriteCreation::title() const
568+
{
569+
return "Sprite Creation";
570+
}
571+
572+
std::string SpriteCreation::subtitle() const
573+
{
574+
#if defined(COCOS2D_DEBUG) && COCOS2D_DEBUG == 1
575+
return "In debug mode";
576+
#else
577+
return "In release mode";
578+
#endif
579+
}
580+
581+
385582
VBOFullTest::VBOFullTest()
386583
{
387584
Size s = Director::getInstance()->getWinSize();
@@ -791,31 +988,88 @@ std::string RendererUniformBatch2::subtitle() const
791988
NonBatchSprites::NonBatchSprites()
792989
{
793990
Size s = Director::getInstance()->getWinSize();
794-
Node* parent = Node::create();
795-
parent->setPosition(0, 0);
796-
addChild(parent);
991+
_spritesAnchor = Node::create();
992+
_spritesAnchor->setPosition(0, 0);
993+
addChild(_spritesAnchor);
994+
995+
996+
_totalSprites = Label::createWithTTF(TTFConfig("fonts/arial.ttf"), "sprites");
997+
_totalSprites->setColor(Color3B::YELLOW);
998+
_totalSprites->enableOutline(Color4B::RED, 2);
999+
_totalSprites->setPosition(s.width/2, s.height/2);
1000+
1001+
addChild(_totalSprites);
1002+
1003+
scheduleUpdate();
1004+
}
1005+
1006+
void NonBatchSprites::createSprite()
1007+
{
7971008

798-
for (int i = 0; i < 2000; ++i)
1009+
Size s = Director::getInstance()->getWinSize();
1010+
Sprite* sprite = nullptr;
1011+
if (_spriteIndex % 2 == 0)
7991012
{
800-
Sprite* sprite = nullptr;
801-
if (i % 2 == 0)
802-
{
803-
sprite = Sprite::create("Images/grossini_dance_05.png");
804-
}
805-
else
806-
{
807-
sprite = Sprite::create("Images/grossini_dance_01.png");
808-
}
1013+
sprite = Sprite::create("Images/grossini_dance_05.png");
1014+
}
1015+
else
1016+
{
1017+
sprite = Sprite::create("Images/grossini_dance_01.png");
1018+
}
8091019

810-
if (!sprite) break;
1020+
if (!sprite) return;
1021+
auto r = rand_0_1() * 0.6 + 0.2;
1022+
sprite->setScale(r, r);
1023+
float x = ((float)std::rand()) / RAND_MAX;
1024+
float y = ((float)std::rand()) / RAND_MAX;
1025+
sprite->runAction(RepeatForever::create(RotateBy::create(1, 45)));
8111026

812-
sprite->setScale(0.1f, 0.1f);
813-
float x = ((float)std::rand()) / RAND_MAX;
814-
float y = ((float)std::rand()) / RAND_MAX;
815-
sprite->runAction(RepeatForever::create(RotateBy::create(1, 45)));
816-
817-
sprite->setPosition(Vec2(x * s.width, y * s.height));
818-
parent->addChild(sprite);
1027+
sprite->setPosition(Vec2(x * s.width, y * s.height));
1028+
_spritesAnchor->addChild(sprite);
1029+
1030+
_spriteIndex++;
1031+
std::stringstream ss;
1032+
ss << _spriteIndex << " sprites";
1033+
_totalSprites->setString(ss.str());
1034+
}
1035+
1036+
void NonBatchSprites::update(float dt)
1037+
{
1038+
1039+
if( dt <= 1.0f / 28.0f && dt >= 1.0f/ 31.0f)
1040+
{
1041+
_around30fps.hit();
1042+
}
1043+
else
1044+
{
1045+
_around30fps.cancel();
1046+
}
1047+
1048+
_maDt = 0.7f * _maDt + 0.3f * dt;
1049+
_rmaDt = 0.5f * _rmaDt + 0.5f * dt;
1050+
if(_maDt <= DEST_DT_30FPS) {
1051+
_contSlow.cancel();
1052+
_contFast.hit();
1053+
if(_contFast.ok()){
1054+
auto t2 = DEST_DT_30FPS - _rmaDt;
1055+
auto delta = (int)(t2 / _rmaDt * _spriteIndex * 0.1);
1056+
delta =std::min(20, std::max(1, delta));
1057+
for(int i =0 ;i< delta; i++) {
1058+
createSprite();
1059+
}
1060+
}
1061+
}else{
1062+
_contSlow.hit();
1063+
_contFast.cancel();
1064+
}
1065+
1066+
if(_contSlow.ok() || _around30fps.ok())
1067+
{
1068+
unscheduleUpdate();
1069+
std::stringstream ss;
1070+
ss << _spriteIndex << " sprites, DONE!";
1071+
_totalSprites->setString(ss.str());
1072+
_totalSprites->setScale(1.2);
8191073
}
8201074
}
8211075

@@ -831,6 +1085,10 @@ std::string NonBatchSprites::title() const
8311085

8321086
std::string NonBatchSprites::subtitle() const
8331087
{
834-
return "simulate lots of sprites";
1088+
#if defined(COCOS2D_DEBUG) && COCOS2D_DEBUG == 1
1089+
return "DEBUG: simulate lots of sprites, drop to 30 fps";
1090+
#else
1091+
return "RELEASE: simulate lots of sprites, drop to 30 fps";
1092+
#endif
8351093
}
8361094

0 commit comments

Comments
 (0)