Merge pull request #11844 from ricardoquesada/perf_fixes

fixes memory leak
This commit is contained in:
Ricardo Quesada 2015-05-14 18:06:27 -07:00
commit e14643afb2
7 changed files with 96 additions and 73 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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
{

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
};