Fix config files (XML) saving performance regression

Instead of writting on hard disk little by little all the time,
all data is collected in a string buffer to write once on the disk at the end.

Fix #10678, fix #10674, close #10691
This commit is contained in:
Don Ho 2021-10-19 01:14:02 +02:00
parent 5d086f93a8
commit 386366d7f2
2 changed files with 43 additions and 39 deletions

View File

@ -23,6 +23,7 @@ distribution.
*/ */
#include <sstream> #include <sstream>
#include <memory>
#include "tinyxml.h" #include "tinyxml.h"
bool TiXmlBase::condenseWhiteSpace = true; bool TiXmlBase::condenseWhiteSpace = true;
@ -551,27 +552,27 @@ void TiXmlElement::SetAttribute( const TCHAR * name, const TCHAR * _value )
} }
} }
void TiXmlElement::Print( Win32_IO_File& cfile, int depth ) const void TiXmlElement::Print( std::string& outputStream, int depth ) const
{ {
int i; int i;
for ( i=0; i<depth; i++ ) for ( i=0; i<depth; i++ )
{ {
cfile.writeStr(" "); outputStream += " ";
//generic_fprintf( cfile, TEXT(" ") ); //generic_fprintf( cfile, TEXT(" ") );
} }
std::string tagOpenValue = "<"; std::string tagOpenValue = "<";
tagOpenValue += wstring2string(value, CP_UTF8); tagOpenValue += wstring2string(value, CP_UTF8);
cfile.writeStr(tagOpenValue); outputStream += tagOpenValue;
//generic_fprintf( cfile, TEXT("<%ls"), value.c_str() ); //generic_fprintf( cfile, TEXT("<%ls"), value.c_str() );
TiXmlAttribute* attrib; TiXmlAttribute* attrib;
for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() ) for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
{ {
cfile.writeStr(" "); outputStream += " ";
//generic_fprintf(cfile, TEXT(" ")); //generic_fprintf(cfile, TEXT(" "));
attrib->Print( cfile, depth ); attrib->Print(outputStream, depth );
} }
// There are 3 different formatting approaches: // There are 3 different formatting approaches:
@ -581,45 +582,45 @@ void TiXmlElement::Print( Win32_IO_File& cfile, int depth ) const
TiXmlNode* node; TiXmlNode* node;
if ( !firstChild ) if ( !firstChild )
{ {
cfile.writeStr(" />"); outputStream += " />";
//generic_fprintf( cfile, TEXT(" />") ); //generic_fprintf( cfile, TEXT(" />") );
} }
else if ( firstChild == lastChild && firstChild->ToText() ) else if ( firstChild == lastChild && firstChild->ToText() )
{ {
cfile.writeStr(">"); outputStream += ">";
//generic_fprintf( cfile, TEXT(">") ); //generic_fprintf( cfile, TEXT(">") );
firstChild->Print( cfile, depth + 1 ); firstChild->Print(outputStream, depth + 1 );
std::string tagCloseWithValue = "</"; std::string tagCloseWithValue = "</";
tagCloseWithValue += wstring2string(value, CP_UTF8) + ">"; tagCloseWithValue += wstring2string(value, CP_UTF8) + ">";
cfile.writeStr(tagCloseWithValue); outputStream += tagCloseWithValue;
//generic_fprintf( cfile, TEXT("</%ls>"), value.c_str() ); //generic_fprintf( cfile, TEXT("</%ls>"), value.c_str() );
} }
else else
{ {
cfile.writeStr(">"); outputStream += ">";
//generic_fprintf( cfile, TEXT(">") ); //generic_fprintf( cfile, TEXT(">") );
for ( node = firstChild; node; node=node->NextSibling() ) for ( node = firstChild; node; node=node->NextSibling() )
{ {
if ( !node->ToText() ) if ( !node->ToText() )
{ {
cfile.writeStr("\r\n"); outputStream += "\r\n";
//generic_fprintf( cfile, TEXT("\n") ); //generic_fprintf( cfile, TEXT("\n") );
} }
node->Print( cfile, depth+1 ); node->Print(outputStream, depth+1 );
} }
cfile.writeStr("\r\n"); outputStream += "\r\n";
//generic_fprintf( cfile, TEXT("\n") ); //generic_fprintf( cfile, TEXT("\n") );
for( i=0; i<depth; ++i ) for( i=0; i<depth; ++i )
cfile.writeStr(" "); outputStream += " ";
// generic_fprintf( cfile, TEXT(" ") ); // generic_fprintf( cfile, TEXT(" ") );
std::string tagCloseWithValue = "</"; std::string tagCloseWithValue = "</";
tagCloseWithValue += wstring2string(value, CP_UTF8) + ">"; tagCloseWithValue += wstring2string(value, CP_UTF8) + ">";
cfile.writeStr(tagCloseWithValue); outputStream += tagCloseWithValue;
//generic_fprintf( cfile, TEXT("</%ls>"), value.c_str() ); //generic_fprintf( cfile, TEXT("</%ls>"), value.c_str() );
} }
} }
@ -793,7 +794,10 @@ bool TiXmlDocument::SaveFile( const TCHAR * filename ) const
if (file.isOpened()) if (file.isOpened())
{ {
Print(file, 0); std::unique_ptr<std::string> outputStr = std::make_unique<std::string>();
Print(*outputStr, 0);
if (!outputStr->empty())
file.writeStr(*outputStr);
return true; return true;
} }
@ -820,14 +824,14 @@ TiXmlNode* TiXmlDocument::Clone() const
} }
void TiXmlDocument::Print( Win32_IO_File& cfile, int depth ) const void TiXmlDocument::Print( std::string& outputStream, int depth ) const
{ {
TiXmlNode* node; TiXmlNode* node;
for ( node=FirstChild(); node; node=node->NextSibling() ) for ( node=FirstChild(); node; node=node->NextSibling() )
{ {
node->Print( cfile, depth ); node->Print(outputStream, depth );
cfile.writeStr("\r\n"); outputStream += "\r\n";
//generic_fprintf( cfile, TEXT("\n") ); //generic_fprintf( cfile, TEXT("\n") );
} }
} }
@ -868,7 +872,7 @@ TiXmlAttribute* TiXmlAttribute::Previous() const
} }
void TiXmlAttribute::Print( Win32_IO_File& cfile, int /*depth*/ ) const void TiXmlAttribute::Print( std::string& outputStream, int /*depth*/ ) const
{ {
TIXML_STRING n, v; TIXML_STRING n, v;
@ -890,7 +894,7 @@ void TiXmlAttribute::Print( Win32_IO_File& cfile, int /*depth*/ ) const
attrVsValue += "'"; attrVsValue += "'";
//generic_fprintf(cfile, TEXT("%ls='%ls'"), n.c_str(), v.c_str()); //generic_fprintf(cfile, TEXT("%ls='%ls'"), n.c_str(), v.c_str());
} }
cfile.writeStr(attrVsValue); outputStream += attrVsValue;
} }
@ -950,18 +954,18 @@ const double TiXmlAttribute::DoubleValue() const
return generic_atof (value.c_str ()); return generic_atof (value.c_str ());
} }
void TiXmlComment::Print( Win32_IO_File& cfile, int depth ) const void TiXmlComment::Print( std::string& outputStream, int depth ) const
{ {
for ( int i=0; i<depth; i++ ) for ( int i=0; i<depth; i++ )
{ {
cfile.writeStr(" "); outputStream += " ";
//generic_fprintf( cfile, TEXT(" ") ); //generic_fprintf( cfile, TEXT(" ") );
} }
std::string comment = "<!--"; std::string comment = "<!--";
comment += wstring2string(value, CP_UTF8); comment += wstring2string(value, CP_UTF8);
comment += "-->"; comment += "-->";
cfile.writeStr(comment); outputStream += comment;
//generic_fprintf( cfile, TEXT("<!--%ls-->"), value.c_str() ); //generic_fprintf( cfile, TEXT("<!--%ls-->"), value.c_str() );
} }
@ -984,12 +988,12 @@ TiXmlNode* TiXmlComment::Clone() const
} }
void TiXmlText::Print( Win32_IO_File& cfile, int /*depth*/ ) const void TiXmlText::Print( std::string& outputStream, int /*depth*/ ) const
{ {
TIXML_STRING buffer; TIXML_STRING buffer;
PutString( value, &buffer ); PutString( value, &buffer );
cfile.writeStr(wstring2string(buffer, CP_UTF8)); outputStream += wstring2string(buffer, CP_UTF8);
//generic_fprintf( cfile, TEXT("%ls"), buffer.c_str() ); //generic_fprintf( cfile, TEXT("%ls"), buffer.c_str() );
} }
@ -1023,7 +1027,7 @@ TiXmlDeclaration::TiXmlDeclaration( const TCHAR * _version,
standalone = _standalone; standalone = _standalone;
} }
void TiXmlDeclaration::Print( Win32_IO_File& cfile, int /*depth*/ ) const void TiXmlDeclaration::Print( std::string& outputStream, int /*depth*/ ) const
{ {
std::string xmlDcl = "<?xml "; std::string xmlDcl = "<?xml ";
//generic_fprintf (cfile, TEXT("<?xml ")); //generic_fprintf (cfile, TEXT("<?xml "));
@ -1054,7 +1058,7 @@ void TiXmlDeclaration::Print( Win32_IO_File& cfile, int /*depth*/ ) const
xmlDcl += "?>"; xmlDcl += "?>";
//generic_fprintf (cfile, TEXT("?>")); //generic_fprintf (cfile, TEXT("?>"));
cfile.writeStr(xmlDcl); outputStream += xmlDcl;
} }
void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const
@ -1097,13 +1101,13 @@ TiXmlNode* TiXmlDeclaration::Clone() const
} }
void TiXmlUnknown::Print( Win32_IO_File& cfile, int depth ) const void TiXmlUnknown::Print( std::string& outputStream, int depth ) const
{ {
for ( int i=0; i<depth; i++ ) for ( int i=0; i<depth; i++ )
cfile.writeStr(" "); outputStream += " ";
//generic_fprintf( cfile, TEXT(" ") ); //generic_fprintf( cfile, TEXT(" ") );
cfile.writeStr(wstring2string(value, CP_UTF8)); outputStream += wstring2string(value, CP_UTF8);
//generic_fprintf( cfile, TEXT("%ls"), value.c_str() ); //generic_fprintf( cfile, TEXT("%ls"), value.c_str() );
} }

View File

@ -132,7 +132,7 @@ public:
(For an unformatted stream, use the << operator.) (For an unformatted stream, use the << operator.)
*/ */
virtual void Print( Win32_IO_File& cfile, int depth ) const = 0; virtual void Print( std::string& outputStream, int depth ) const = 0;
/** The world does not agree on whether white space should be kept or /** The world does not agree on whether white space should be kept or
not. In order to make everyone happy, these global, static functions not. In order to make everyone happy, these global, static functions
@ -640,7 +640,7 @@ public:
virtual const TCHAR* Parse( const TCHAR* p, TiXmlParsingData* data ); virtual const TCHAR* Parse( const TCHAR* p, TiXmlParsingData* data );
// [internal use] // [internal use]
virtual void Print( Win32_IO_File& cfile, int depth ) const; virtual void Print( std::string& outputStream, int depth ) const;
virtual void StreamOut( TIXML_OSTREAM * out ) const; virtual void StreamOut( TIXML_OSTREAM * out ) const;
// [internal use] // [internal use]
@ -784,7 +784,7 @@ public:
virtual TiXmlNode* Clone() const; virtual TiXmlNode* Clone() const;
// [internal use] // [internal use]
virtual void Print( Win32_IO_File& cfile, int depth ) const; virtual void Print( std::string& outputStream, int depth ) const;
protected: protected:
@ -823,7 +823,7 @@ public:
// [internal use] Creates a new Element and returs it. // [internal use] Creates a new Element and returs it.
virtual TiXmlNode* Clone() const; virtual TiXmlNode* Clone() const;
// [internal use] // [internal use]
virtual void Print( Win32_IO_File& cfile, int depth ) const; virtual void Print( std::string& outputStream, int depth ) const;
protected: protected:
// used to be public // used to be public
#ifdef TIXML_USE_STL #ifdef TIXML_USE_STL
@ -860,7 +860,7 @@ public:
#endif #endif
// [internal use] // [internal use]
virtual void Print( Win32_IO_File& cfile, int depth ) const; virtual void Print( std::string& outputStream, int depth ) const;
protected : protected :
// [internal use] Creates a new Element and returns it. // [internal use] Creates a new Element and returns it.
@ -929,7 +929,7 @@ public:
// [internal use] Creates a new Element and returs it. // [internal use] Creates a new Element and returs it.
virtual TiXmlNode* Clone() const; virtual TiXmlNode* Clone() const;
// [internal use] // [internal use]
virtual void Print( Win32_IO_File& cfile, int depth ) const; virtual void Print( std::string& outputStream, int depth ) const;
protected: protected:
// used to be public // used to be public
@ -964,7 +964,7 @@ public:
// [internal use] // [internal use]
virtual TiXmlNode* Clone() const; virtual TiXmlNode* Clone() const;
// [internal use] // [internal use]
virtual void Print( Win32_IO_File& cfile, int depth ) const; virtual void Print( std::string& outputStream, int depth ) const;
protected: protected:
#ifdef TIXML_USE_STL #ifdef TIXML_USE_STL
virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ); virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
@ -1101,7 +1101,7 @@ public:
void Print() const { /*Print(stdout, 0);*/ } void Print() const { /*Print(stdout, 0);*/ }
// [internal use] // [internal use]
virtual void Print( Win32_IO_File& cfile, int depth = 0 ) const; virtual void Print( std::string& outputStream, int depth = 0 ) const;
// [internal use] // [internal use]
void SetError( int err, const TCHAR* errorLocation, TiXmlParsingData* prevData ); void SetError( int err, const TCHAR* errorLocation, TiXmlParsingData* prevData );