Discussion:
Performance of CString::Replace
(too old to reply)
dududuil
2010-04-23 08:07:01 UTC
Permalink
hi all,
I have a huge application that does a lot of strings manipulations.
Analyzing its performance, I have noticed that a lot of time is spend in
CString::Replace.

calls like :
str.Replace("\n","\n\t"); or
str.Replace("\r", "\0x00");
take lots of time. (25% of overall performance !!)

How can I improve the performance?
David Lowndes
2010-04-23 09:22:08 UTC
Permalink
Post by dududuil
I have a huge application that does a lot of strings manipulations.
Analyzing its performance, I have noticed that a lot of time is spend in
CString::Replace.
str.Replace("\n","\n\t"); or
str.Replace("\r", "\0x00");
take lots of time. (25% of overall performance !!)
If you change the second example to:

str.Replace( '\r', '\0x00');

It might result in some improvement.

However the first example needs to insert an extra character, so
there's no easy way to alter the fact that the string will require
reallocation - which is likely to be the main hog.

Dave
Ulrich Eckhardt
2010-04-23 10:27:22 UTC
Permalink
Post by dududuil
I have a huge application that does a lot of strings manipulations.
Analyzing its performance, I have noticed that a lot of time is spend in
CString::Replace.
str.Replace("\n","\n\t"); or
str.Replace("\r", "\0x00");
take lots of time. (25% of overall performance !!)
How can I improve the performance?
The call to Replace() has to allocate a second buffer, transform the content
accordingly into the new buffer and then release the old one. It's the
allocating and releasing that probably takes the performance, or at least
it's the part that can be avoided mostly.

If you actually have more than one call to Replace() on the same string,
consider rolling your own function that does the replacements. If you have
the two above, I'd do it like this:

CString tmp;
tmp.Reserve(str.GetLength()); // preallocate, not sure if MFC allow this
for(int i=0, len=str.GetLength(); i!=len; ++i)
{
switch(str[i]) {
case '\n': tmp += "\n\t"; break;
case '\r': tmp += "\0x00"; break;
default: tmp += str[i]; break;
}
}
str = tmp;

The preallocation makes the target string overallocate its internal buffer,
so that not every call that adds something causes an allocation.

Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
dududuil
2010-04-26 11:51:01 UTC
Permalink
I have failed to find how to preallocate a CString to a certin size - does
anyone know how can I set the size of a CString ?
Post by Ulrich Eckhardt
Post by dududuil
I have a huge application that does a lot of strings manipulations.
Analyzing its performance, I have noticed that a lot of time is spend in
CString::Replace.
str.Replace("\n","\n\t"); or
str.Replace("\r", "\0x00");
take lots of time. (25% of overall performance !!)
How can I improve the performance?
The call to Replace() has to allocate a second buffer, transform the content
accordingly into the new buffer and then release the old one. It's the
allocating and releasing that probably takes the performance, or at least
it's the part that can be avoided mostly.
If you actually have more than one call to Replace() on the same string,
consider rolling your own function that does the replacements. If you have
CString tmp;
tmp.Reserve(str.GetLength()); // preallocate, not sure if MFC allow this
for(int i=0, len=str.GetLength(); i!=len; ++i)
{
switch(str[i]) {
case '\n': tmp += "\n\t"; break;
case '\r': tmp += "\0x00"; break;
default: tmp += str[i]; break;
}
}
str = tmp;
The preallocation makes the target string overallocate its internal buffer,
so that not every call that adds something causes an allocation.
Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
.
Doug Harrison [MVP]
2010-04-26 17:50:39 UTC
Permalink
On Mon, 26 Apr 2010 04:51:01 -0700, dududuil
Post by dududuil
I have failed to find how to preallocate a CString to a certin size - does
anyone know how can I set the size of a CString ?
CSimpleStringT::Preallocate. Microsoft made the CString documentation
pretty inscrutable a couple of versions ago, and you have to look at
CStringT and its base class CSimpleStringT at a minimum.
--
Doug Harrison
Visual C++ MVP
Tom Serface
2010-04-27 00:51:46 UTC
Permalink
You can also create a CString using the constructor:

CString(TCHARch,intnRepeat=1);

Where the repeat character is the number of characters you want ultimately.

You might also want to try a regex engine like boost to see if that is
faster:

http://onlamp.com/pub/a/onlamp/2006/04/06/boostregex.html

Tom
Post by dududuil
I have failed to find how to preallocate a CString to a certin size - does
anyone know how can I set the size of a CString ?
Post by Ulrich Eckhardt
Post by dududuil
I have a huge application that does a lot of strings manipulations.
Analyzing its performance, I have noticed that a lot of time is spend in
CString::Replace.
str.Replace("\n","\n\t"); or
str.Replace("\r", "\0x00");
take lots of time. (25% of overall performance !!)
How can I improve the performance?
The call to Replace() has to allocate a second buffer, transform the content
accordingly into the new buffer and then release the old one. It's the
allocating and releasing that probably takes the performance, or at least
it's the part that can be avoided mostly.
If you actually have more than one call to Replace() on the same string,
consider rolling your own function that does the replacements. If you have
CString tmp;
tmp.Reserve(str.GetLength()); // preallocate, not sure if MFC allow this
for(int i=0, len=str.GetLength(); i!=len; ++i)
{
switch(str[i]) {
case '\n': tmp += "\n\t"; break;
case '\r': tmp += "\0x00"; break;
default: tmp += str[i]; break;
}
}
str = tmp;
The preallocation makes the target string overallocate its internal buffer,
so that not every call that adds something causes an allocation.
Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
.
Loading...