mirror of https://github.com/axmolengine/axmol.git
Merge pull request #11844 from ricardoquesada/perf_fixes
fixes memory leak
This commit is contained in:
commit
e14643afb2
|
@ -40,6 +40,8 @@ NS_CC_BEGIN
|
|||
|
||||
class CC_DLL Data
|
||||
{
|
||||
friend class Properties;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This parameter is defined for convenient reference if a null Data object is needed.
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
|
||||
|
||||
#include "CCProperties.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "platform/CCPlatformMacros.h"
|
||||
#include "platform/CCFileUtils.h"
|
||||
#include "math/Vec2.h"
|
||||
|
@ -32,37 +35,8 @@
|
|||
#include "deprecated/CCString.h"
|
||||
|
||||
|
||||
|
||||
USING_NS_CC;
|
||||
|
||||
static void printProperties(Properties* properties)
|
||||
{
|
||||
// Print the name and ID of the current namespace.
|
||||
const char* spacename = properties->getNamespace();
|
||||
const char* id = properties->getId();
|
||||
CCLOG("Namespace: %s ID: %s\n{", spacename, id);
|
||||
|
||||
// Print all properties in this namespace.
|
||||
const char* name = properties->getNextProperty();
|
||||
const char* value = NULL;
|
||||
while (name != NULL)
|
||||
{
|
||||
value = properties->getString(name);
|
||||
CCLOG("%s = %s", name, value);
|
||||
name = properties->getNextProperty();
|
||||
}
|
||||
|
||||
// Print the properties of every namespace within this one.
|
||||
Properties* space = properties->getNextNamespace();
|
||||
while (space != NULL)
|
||||
{
|
||||
printProperties(space);
|
||||
space = properties->getNextNamespace();
|
||||
}
|
||||
|
||||
CCLOG("}\n");
|
||||
}
|
||||
|
||||
// Utility functions (shared with SceneLoader).
|
||||
/** @script{ignore} */
|
||||
void calculateNamespacePath(const std::string& urlString, std::string& fileString, std::vector<std::string>& namespacePath);
|
||||
|
@ -72,6 +46,7 @@ Properties* getPropertiesFromNamespacePath(Properties* properties, const std::ve
|
|||
Properties::Properties()
|
||||
: _variables(nullptr), _dirPath(nullptr), _parent(nullptr), _dataIdx(nullptr), _data(nullptr)
|
||||
{
|
||||
_properties.reserve(32);
|
||||
}
|
||||
|
||||
Properties::Properties(const Properties& copy)
|
||||
|
@ -80,12 +55,10 @@ Properties::Properties(const Properties& copy)
|
|||
_dataIdx(copy._dataIdx), _data(copy._data)
|
||||
{
|
||||
setDirectoryPath(copy._dirPath);
|
||||
_namespaces = std::vector<Properties*>();
|
||||
std::vector<Properties*>::const_iterator it;
|
||||
for (it = copy._namespaces.begin(); it < copy._namespaces.end(); ++it)
|
||||
|
||||
for (const auto space: copy._namespaces)
|
||||
{
|
||||
GP_ASSERT(*it);
|
||||
_namespaces.push_back(new (std::nothrow) Properties(**it));
|
||||
_namespaces.push_back(new (std::nothrow) Properties(*space));
|
||||
}
|
||||
rewind();
|
||||
}
|
||||
|
@ -112,7 +85,7 @@ Properties::Properties(Data* data, ssize_t* dataIdx, const std::string& name, co
|
|||
rewind();
|
||||
}
|
||||
|
||||
Properties* Properties::create(const std::string& url)
|
||||
Properties* Properties::createWithoutAutorelease(const std::string& url)
|
||||
{
|
||||
if (url.size() == 0)
|
||||
{
|
||||
|
@ -214,7 +187,7 @@ void Properties::readProperties()
|
|||
else
|
||||
{
|
||||
trimWhiteSpace(line);
|
||||
const int len = strlen(line);
|
||||
const auto len = strlen(line);
|
||||
if (len >= 2 && strncmp(line + (len - 2), "*/", 2) == 0)
|
||||
comment = false;
|
||||
}
|
||||
|
@ -441,7 +414,7 @@ signed char Properties::readChar()
|
|||
{
|
||||
if (eof())
|
||||
return EOF;
|
||||
return _data->getBytes()[(*_dataIdx)++];
|
||||
return _data->_bytes[(*_dataIdx)++];
|
||||
}
|
||||
|
||||
char* Properties::readLine(char* output, int num)
|
||||
|
@ -451,15 +424,20 @@ char* Properties::readLine(char* output, int num)
|
|||
if (eof())
|
||||
return nullptr;
|
||||
|
||||
auto c = readChar();
|
||||
while (c!=EOF && c!='\n' && idx-1<num)
|
||||
{
|
||||
output[idx++] = c;
|
||||
c = readChar();
|
||||
// little optimization: avoid uneeded dereferences
|
||||
ssize_t dataIdx = *_dataIdx;
|
||||
|
||||
while (dataIdx<_data->_size && _data->_bytes[dataIdx]!='\n' && idx-1<num)
|
||||
{
|
||||
dataIdx++; idx++;
|
||||
}
|
||||
|
||||
memcpy(output, &_data->_bytes[*_dataIdx], idx);
|
||||
output[idx] = '\0';
|
||||
|
||||
// restore value
|
||||
*_dataIdx = dataIdx;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
@ -472,7 +450,7 @@ bool Properties::seekFromCurrent(int offset)
|
|||
|
||||
bool Properties::eof()
|
||||
{
|
||||
return (*_dataIdx >= _data->getSize());
|
||||
return (*_dataIdx >= _data->_size);
|
||||
}
|
||||
|
||||
void Properties::skipWhiteSpace()
|
||||
|
@ -563,10 +541,9 @@ void Properties::resolveInheritance(const char* id)
|
|||
derived->_properties = parent->_properties;
|
||||
derived->_namespaces = std::vector<Properties*>();
|
||||
std::vector<Properties*>::const_iterator itt;
|
||||
for (itt = parent->_namespaces.begin(); itt < parent->_namespaces.end(); ++itt)
|
||||
for (const auto space: parent->_namespaces)
|
||||
{
|
||||
GP_ASSERT(*itt);
|
||||
derived->_namespaces.push_back(new (std::nothrow) Properties(**itt));
|
||||
derived->_namespaces.push_back(new (std::nothrow) Properties(*space));
|
||||
}
|
||||
derived->rewind();
|
||||
|
||||
|
@ -595,7 +572,7 @@ void Properties::resolveInheritance(const char* id)
|
|||
|
||||
void Properties::mergeWith(Properties* overrides)
|
||||
{
|
||||
GP_ASSERT(overrides);
|
||||
CCASSERT(overrides, "Invalid overrides");
|
||||
|
||||
// Overwrite or add each property found in child.
|
||||
overrides->rewind();
|
||||
|
@ -685,7 +662,7 @@ void Properties::rewind()
|
|||
|
||||
Properties* Properties::getNamespace(const char* id, bool searchNames, bool recurse) const
|
||||
{
|
||||
GP_ASSERT(id);
|
||||
CCASSERT(id, "invalid id");
|
||||
|
||||
for (std::vector<Properties*>::const_iterator it = _namespaces.begin(); it < _namespaces.end(); ++it)
|
||||
{
|
||||
|
@ -720,7 +697,7 @@ bool Properties::exists(const char* name) const
|
|||
if (name == NULL)
|
||||
return false;
|
||||
|
||||
for (std::list<Property>::const_iterator itr = _properties.begin(); itr != _properties.end(); ++itr)
|
||||
for (std::vector<Property>::const_iterator itr = _properties.begin(); itr != _properties.end(); ++itr)
|
||||
{
|
||||
if (itr->name == name)
|
||||
return true;
|
||||
|
@ -731,7 +708,7 @@ bool Properties::exists(const char* name) const
|
|||
|
||||
static const bool isStringNumeric(const char* str)
|
||||
{
|
||||
GP_ASSERT(str);
|
||||
CCASSERT(str, "invalid str");
|
||||
|
||||
// The first character may be '-'
|
||||
if (*str == '-')
|
||||
|
@ -810,7 +787,7 @@ const char* Properties::getString(const char* name, const char* defaultValue) co
|
|||
return getVariable(variable, defaultValue);
|
||||
}
|
||||
|
||||
for (std::list<Property>::const_iterator itr = _properties.begin(); itr != _properties.end(); ++itr)
|
||||
for (std::vector<Property>::const_iterator itr = _properties.begin(); itr != _properties.end(); ++itr)
|
||||
{
|
||||
if (itr->name == name)
|
||||
{
|
||||
|
@ -844,7 +821,7 @@ bool Properties::setString(const char* name, const char* value)
|
|||
{
|
||||
if (name)
|
||||
{
|
||||
for (std::list<Property>::iterator itr = _properties.begin(); itr != _properties.end(); ++itr)
|
||||
for (std::vector<Property>::iterator itr = _properties.begin(); itr != _properties.end(); ++itr)
|
||||
{
|
||||
if (itr->name == name)
|
||||
{
|
||||
|
@ -939,7 +916,7 @@ long Properties::getLong(const char* name) const
|
|||
|
||||
bool Properties::getMat4(const char* name, Mat4* out) const
|
||||
{
|
||||
GP_ASSERT(out);
|
||||
CCASSERT(out, "Invalid out");
|
||||
|
||||
const char* valueString = getString(name);
|
||||
if (valueString)
|
||||
|
@ -997,7 +974,7 @@ bool Properties::getColor(const char* name, Vec4* out) const
|
|||
|
||||
bool Properties::getPath(const char* name, std::string* path) const
|
||||
{
|
||||
GP_ASSERT(name && path);
|
||||
CCASSERT(name && path, "Invalid name or path");
|
||||
const char* valueString = getString(name);
|
||||
if (valueString)
|
||||
{
|
||||
|
@ -1052,7 +1029,7 @@ const char* Properties::getVariable(const char* name, const char* defaultValue)
|
|||
|
||||
void Properties::setVariable(const char* name, const char* value)
|
||||
{
|
||||
GP_ASSERT(name);
|
||||
CCASSERT(name, "Invalid name");
|
||||
|
||||
Property* prop = NULL;
|
||||
|
||||
|
@ -1102,7 +1079,7 @@ Properties* Properties::clone()
|
|||
|
||||
for (size_t i = 0, count = _namespaces.size(); i < count; i++)
|
||||
{
|
||||
GP_ASSERT(_namespaces[i]);
|
||||
CCASSERT(_namespaces[i], "Invalid namespace");
|
||||
Properties* child = _namespaces[i]->clone();
|
||||
p->_namespaces.push_back(child);
|
||||
child->_parent = p;
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <string>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#include "renderer/CCTexture2D.h"
|
||||
#include "platform/CCPlatformMacros.h"
|
||||
|
@ -105,7 +105,7 @@ class Data;
|
|||
|
||||
@verbatim
|
||||
// Create the top-level Properties object.
|
||||
Properties* properties = Properties::create("example.properties");
|
||||
Properties* properties = Properties::createWithoutAutorelease("example.properties");
|
||||
// Retrieve the "spriteTexture" namespace.
|
||||
Properties* spriteTexture = properties->getNamespace("spriteTexture");
|
||||
|
||||
|
@ -187,7 +187,7 @@ public:
|
|||
* @return The created Properties or NULL if there was an error.
|
||||
* @script{create}
|
||||
*/
|
||||
static Properties* create(const std::string& url);
|
||||
static Properties* createWithoutAutorelease(const std::string& url);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
|
@ -579,7 +579,7 @@ private:
|
|||
bool seekFromCurrent(int offset);
|
||||
bool eof();
|
||||
|
||||
// Called after create(); copies info from parents into derived namespaces.
|
||||
// Called after createWithoutAutorelease(); copies info from parents into derived namespaces.
|
||||
void resolveInheritance(const char* id = NULL);
|
||||
|
||||
// Called by resolveInheritance().
|
||||
|
@ -602,8 +602,8 @@ private:
|
|||
std::string _namespace;
|
||||
std::string _id;
|
||||
std::string _parentID;
|
||||
std::list<Property> _properties;
|
||||
std::list<Property>::iterator _propertiesItr;
|
||||
std::vector<Property> _properties;
|
||||
std::vector<Property>::iterator _propertiesItr;
|
||||
std::vector<Properties*> _namespaces;
|
||||
std::vector<Properties*>::const_iterator _namespacesItr;
|
||||
std::vector<Property>* _variables;
|
||||
|
|
|
@ -561,12 +561,13 @@ static Data getData(const std::string& filename, bool forString)
|
|||
mode = "rt";
|
||||
else
|
||||
mode = "rb";
|
||||
|
||||
|
||||
auto fileutils = FileUtils::getInstance();
|
||||
do
|
||||
{
|
||||
// Read the file from hardware
|
||||
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(filename);
|
||||
FILE *fp = fopen(FileUtils::getInstance()->getSuitableFOpen(fullPath).c_str(), mode);
|
||||
std::string fullPath = fileutils->fullPathForFilename(filename);
|
||||
FILE *fp = fopen(fileutils->getSuitableFOpen(fullPath).c_str(), mode);
|
||||
CC_BREAK_IF(!fp);
|
||||
fseek(fp,0,SEEK_END);
|
||||
size = ftell(fp);
|
||||
|
@ -593,9 +594,7 @@ static Data getData(const std::string& filename, bool forString)
|
|||
|
||||
if (nullptr == buffer || 0 == readsize)
|
||||
{
|
||||
std::string msg = "Get data from file(";
|
||||
msg.append(filename).append(") failed!");
|
||||
CCLOG("%s", msg.c_str());
|
||||
CCLOG("Get data from file %s failed", filename.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -109,10 +109,13 @@ bool Material::initWithFile(const std::string& validfilename)
|
|||
char* bytes = (char*)data.getBytes();
|
||||
bytes[data.getSize()-1]='\0';
|
||||
|
||||
Properties* properties = Properties::create(validfilename);
|
||||
// Warning: properties is not a "Ref" object, must be manually deleted
|
||||
Properties* properties = Properties::createWithoutAutorelease(validfilename);
|
||||
|
||||
// get the first material
|
||||
parseProperties((strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace());
|
||||
|
||||
CC_SAFE_DELETE(properties);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include "MaterialSystemTest.h"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include "../testResource.h"
|
||||
#include "cocos2d.h"
|
||||
|
||||
|
@ -42,6 +45,7 @@ MaterialSystemTest::MaterialSystemTest()
|
|||
ADD_TEST_CASE(Material_clone);
|
||||
ADD_TEST_CASE(Material_MultipleSprite3D);
|
||||
ADD_TEST_CASE(Material_Sprite3DTest);
|
||||
ADD_TEST_CASE(Material_parsePerformance);
|
||||
}
|
||||
|
||||
std::string MaterialSystemBaseTest::title() const
|
||||
|
@ -107,7 +111,7 @@ void Material_2DEffects::onEnter()
|
|||
{
|
||||
MaterialSystemBaseTest::onEnter();
|
||||
|
||||
auto properties = Properties::create("Materials/2d_effects.material#sample");
|
||||
auto properties = Properties::createWithoutAutorelease("Materials/2d_effects.material#sample");
|
||||
|
||||
// Print the properties of every namespace within this one.
|
||||
printProperties(properties, 0);
|
||||
|
@ -133,6 +137,9 @@ void Material_2DEffects::onEnter()
|
|||
spriteEdgeDetect->setNormalizedPosition(Vec2(0.8, 0.5));
|
||||
this->addChild(spriteEdgeDetect);
|
||||
spriteEdgeDetect->setGLProgramState(mat1->getTechniqueByName("edge_detect")->getPassByIndex(0)->getGLProgramState());
|
||||
|
||||
// properties is not a "Ref" object
|
||||
CC_SAFE_DELETE(properties);
|
||||
}
|
||||
|
||||
std::string Material_2DEffects::subtitle() const
|
||||
|
@ -250,6 +257,32 @@ std::string Material_clone::subtitle() const
|
|||
return "Testing material->clone()";
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
void Material_parsePerformance::onEnter()
|
||||
{
|
||||
MaterialSystemBaseTest::onEnter();
|
||||
|
||||
std::clock_t begin = std::clock();
|
||||
|
||||
for(int i=0;i<5000;i++)
|
||||
{
|
||||
Material::createWithFilename("Materials/2d_effects.material");
|
||||
Material::createWithFilename("Materials/3d_effects.material");
|
||||
}
|
||||
|
||||
std::clock_t end = std::clock();
|
||||
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
||||
|
||||
log("Parsing took: %f", elapsed_secs);
|
||||
}
|
||||
|
||||
std::string Material_parsePerformance::subtitle() const
|
||||
{
|
||||
return "Testing parsing performance";
|
||||
}
|
||||
|
||||
// MARK: Helper functions
|
||||
|
||||
static void printProperties(Properties* properties, int indent)
|
||||
|
@ -263,7 +296,7 @@ static void printProperties(Properties* properties, int indent)
|
|||
chindent[i] = ' ';
|
||||
chindent[i] = '\0';
|
||||
|
||||
CCLOG("%sNamespace: %s ID: %s\n%s{", chindent, spacename, id, chindent);
|
||||
log("%sNamespace: %s ID: %s\n%s{", chindent, spacename, id, chindent);
|
||||
|
||||
// Print all properties in this namespace.
|
||||
const char* name = properties->getNextProperty();
|
||||
|
@ -271,7 +304,7 @@ static void printProperties(Properties* properties, int indent)
|
|||
while (name != NULL)
|
||||
{
|
||||
value = properties->getString(name);
|
||||
CCLOG("%s%s = %s", chindent, name, value);
|
||||
log("%s%s = %s", chindent, name, value);
|
||||
name = properties->getNextProperty();
|
||||
}
|
||||
|
||||
|
@ -282,5 +315,5 @@ static void printProperties(Properties* properties, int indent)
|
|||
space = properties->getNextNamespace();
|
||||
}
|
||||
|
||||
CCLOG("%s}\n",chindent);
|
||||
log("%s}\n",chindent);
|
||||
}
|
||||
|
|
|
@ -86,4 +86,13 @@ public:
|
|||
virtual std::string subtitle() const override;
|
||||
};
|
||||
|
||||
class Material_parsePerformance : public MaterialSystemBaseTest
|
||||
{
|
||||
public:
|
||||
CREATE_FUNC(Material_parsePerformance);
|
||||
|
||||
virtual void onEnter() override;
|
||||
virtual std::string subtitle() const override;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue