A couple of questions re CString -vs- std::string ...
1. What are the pros and cons of using CString -vs- std::string ?
2. If you were going to pick one to be your primary string type til the end of time, which would you pick?
Thanks
Printable View
A couple of questions re CString -vs- std::string ...
1. What are the pros and cons of using CString -vs- std::string ?
2. If you were going to pick one to be your primary string type til the end of time, which would you pick?
Thanks
std::string is part of the C++ Standard so, IMO, that is the best choice
And please do a search.. There have been oodles of threads about this in the past.
Never take something with you for ever. New things often appear and you should always use what is the best. There are pro and cons for the string but just do a research on the forum. As for myself, when I am doing a MFC project a use CString.Quote:
Originally Posted by rlewkov
If you're using MFC, CString is a far better choice over std::string.
IMHO, CString is the only MFC class that is better then the STL version.
The std::string that comes with VC++ 6.0/7.x is very inefficient compare to CString.
std::string peforms very badly compare to CString.
Also IMHO, CString has a better string interface then std::string does.
CString is also easier to code when you want to be able to compile a project to either UNICODE or ANSI.
CString has an operator LPCTSTR(), so you don't have to explicitly cast.
With std::string, you have to use the c_str() member function to pass the pointer.
This point can also be consider a CON, but IMHO, the benifit far aways the down side.
CString has a GetBuffer() function which allows you to modify the buffer directly.
According to the C++ standard there's no portable way to modify the std::string buffer directly.
CString has a CompareNoCase function so you can make case insensitive comparisons.
CString works easier with many MFC and Windows API functions.
The major CON with CString is that is not portable. However, there are some CString versions on the net that are portable.
Well...I do not want to get into all of the above since our view is very different from each other in this case, however....the above is not really true...there is of course a portable way...using a 'vector' as a temporary buffer... :cool:Quote:
Originally Posted by Axter
My comment is true.Quote:
Originally Posted by Andreas Masur
Even if you use vector as a temporary buffer, you're still not modifying the buffer directly.
There are many ways to modify the std::string buffer indirectly. But my comment reffers to direct modification.
You have to show this to us in terms of real code. Badly doing what operations?Quote:
Originally Posted by Axter
Maybe MFC functions that require a CString, but I don't see how a Windows API function would be easier with CString as opposed to std::string.Quote:
CString works easier with many MFC and Windows API functions.
And many of those versions actually wrap std::string with calls that mimic CString.Quote:
The major CON with CString is that is not portable. However, there are some CString versions on the net that are portable.
The one disadvantage to CString that has not been pointed out is that std::string handles binary data easily with no tricks. I don't know if CString can handle binary data (for example, appending binary data on a CString that may contain embedded NULLs). In that respect, std::string has the functions to handle binary data (i.e, append(), data(), assign(), etc.), that AFAIK do not exist in CString.Quote:
Also IMHO, CString has a better string interface then std::string does
Regards,
Paul McKenzie
If you run the code below, you'll see the peformance difference between CString and std::string.Quote:
Originally Posted by Paul McKenzie
Run the test in release mode (not debug).
The code below will show that CString out peformance std::string by a factor of MORE then 10 to 1.
Compile in VC++ 6.0 using std::string that comes with VC++.
Code:int dummy_var = 0;
void function1(const char*Data)
{
CString strData = Data;
dummy_var += strData[99];
}
void function2(const char*Data)
{
std::string strData = Data;
dummy_var += strData[99];
}
void function3(const char*Data)
{
CString strData;
strData = Data;
dummy_var += strData[99];
}
void function4(const char*Data)
{
std::string strData(513, 0);
strData = Data;
dummy_var += strData[99];
}
void function5(const char*Data)
{
std::string strData(999, 0);
strData = Data;
dummy_var += strData[99];
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
const QtyTimesTest = 99999;
DWORD StartTime, LenTime1=0, LenTime2=0, LenTime3=0, LenTime4=0, LenTime5=0;
const int SizeData = 512;
char DummyData[SizeData+1];
memset(DummyData, 'x', SizeData);
DummyData[SizeData] = 0;
{
StartTime = GetTickCount();
for (int i = 0;i < QtyTimesTest;++i)
{
function1(DummyData);
}
LenTime1 += (GetTickCount() - StartTime);
}
{
StartTime = GetTickCount();
for (int i = 0;i < QtyTimesTest;++i)
{
function2(DummyData);
}
LenTime2 += (GetTickCount() - StartTime);
}
{
StartTime = GetTickCount();
for (int i = 0;i < QtyTimesTest;++i)
{
function3(DummyData);
}
LenTime3 += (GetTickCount() - StartTime);
}
{
StartTime = GetTickCount();
for (int i = 0;i < QtyTimesTest;++i)
{
function4(DummyData);
}
LenTime4 += (GetTickCount() - StartTime);
}
{
StartTime = GetTickCount();
for (int i = 0;i < QtyTimesTest;++i)
{
function5(DummyData);
}
LenTime5 += (GetTickCount() - StartTime);
}
printf("Time duration is as follow:\n\
LenTime1 = %li\n\
LenTime2 = %li\n\
LenTime3 = %li\n\
LenTime4 = %li\n\
LenTime5 = %li\n",
LenTime1, LenTime2, LenTime3, LenTime4, LenTime5);
if (!dummy_var) printf("dummy %i", dummy_var);
system("pause");
Example:Quote:
Originally Posted by Paul McKenzie
int MessageBox(
HWND hWnd, // handle to owner window
LPCTSTR lpText, // text in message box
LPCTSTR lpCaption, // message box title
UINT uType // message box style
);
The CString variable is handed over to the API function directly, without having to call a member function. Moreover, it compiles on UNICODE and ANSI projects without having to modify the code, or create another compiler directive.Code:CString CstrData = _T("Hello");
std::string stdStrData = "Hello";
MessageBox(NULL, CstrData, NULL, 0); //Compiles on UNICODE and ANSI
MessageBox(NULL, stdStrData.c_str(), NULL, 0); //Only compiles on ANSI (need wstring for UNICODE)
I agree.Quote:
Originally Posted by Paul McKenzie
CString can also handle binary data.Quote:
Originally Posted by Paul McKenzie
Example code:
More over, the GetBuffer() function can be used similar to the data() function of std::string.Code:char data1[] = "\0\1\2\3\4\5\6\7 Hello World";
char data2[] = "\0\7\6\5\4\3\2\1";
CString binData(data1, sizeof(data1)-1);
binData += CString(data2, sizeof(data2)-1);
for (int i = 0;i < binData.GetLength();++i)
{
cout << (int)binData[i] << endl;
}
system("pause");
I agree that not having an assign() nor an append() function is a limitation on the CString class. And I'm surprise MS didn't include these functions.
However, you can do an append by using the += operator as in my above example. And an assign can be done by either iterating through each position via SetAt, or modifying the buffer directly via GetBuffer() function.
A lot of critics of CString, don't fully understand the class, and don't realize the average peformance value.
Do a reserve() on the string before using it. Then you should see hardly any difference.Quote:
f you run the code below, you'll see the peformance difference between CString and std::string.
Run the test in release mode (not debug).
The code below will show that CString out peformance std::string by a factor of MORE then 10 to 1.
Compile in VC++ 6.0 using std::string that comes with VC++.
Almost all of the standard container classes, including std::string, has a reserve() method that addresses the issue that you demonstrated in your code. The ones that don't are the associative types (maps).
In general, what usually ends up in real code is a series of many concatenations on one string. Why not run a benchmark on that, since that is what is more likely to be done in a real application.
Regards,
Paul McKenzie
You're not being fair to std::string with your ANSI vs UNICODE example. Add this to your project:
and we're on a more equal footing, since that's what happens with CString, anyway. Then the only difference is between the two is that you have to call the c_str() function on the tstring. To my mind that is a distinct advantage that string has over CString. Take the implicit conversion out of CString and it will be a much better class. I also don't like the GetBuffer() function of CString - it opens it up to all sorts of potential problems.Code:#ifdef _UNICODE
typedef tstring std::wstring;
#else
typedef tstring std::string;
#endif
Also, I ran your code. There is hardly any difference in the times, even without reserve():
Running VC 6.0, Pentium 4, 3.00 GHZQuote:
Time duration is as follow:
LenTime1 = 109
LenTime2 = 141
LenTime3 = 93
LenTime4 = 188
LenTime5 = 203
Regards,
Paul McKenzie
That is not exactly what happens with CString. The CString type char itself is change instead of the entire object.Quote:
Originally Posted by Graham
IMHO, the advantages of implicit conversion out ways the disadvantages.
I guess we'll have to agree to disagree.
Did you run it in release or debug mode?Quote:
Originally Posted by Paul McKenzie
Those results look like debug results, and not release.
FYI:
Even in your results, the std::string is about 40% slower the CString.
That's a big difference to me.
And using reserve is not a valid argument for this test. You don't always know the size that you're going to need for your buffer in advance.
Release mode (maximize speed).
For debug, I get these numbers:
Regards,Quote:
Time duration is as follow:
LenTime1 = 234
LenTime2 = 203
LenTime3 = 344
LenTime4 = 422
LenTime5 = 437
Paul McKenzie
Even in your results, the std::string is about 40% slower the CString.
That's a big difference to me.
And using reserve is not a valid argument for this test. You don't always know the size that you're going to need for your buffer in advance.
I made a mistake and thought you were concatenating. All you really tested was the access time to get to a certain element. Therefore you tested one particular trait of CString against std::string.
Most applications (as my previous post suggested) attempt to concatenate, search, substring, etc. a string. Finding the 100th element in a string is not something that would be done repeatedly in a loop.
Regards,
Paul McKenzie
That was just one test.Quote:
Originally Posted by Paul McKenzie
I have peform other test comparing std::string peformance with CString, and on most test CString out peformance std::string.
There are specific senerios in which std::string is more efficient, but on normal average usage, CString is far more efficient.
I like to point out, that I'm only making this comparison with the std::string that comes with VC++.
There are probably third party std::string classes that do a much better job, and probably out peforms CString. But the VC++ std::string class is not one of them.
Possibly. I heard that PJ Plauger improved on the std::string in VC 7.0, but I'm not sure.Quote:
Originally Posted by Axter
Anyway, I changed your code to do a concatenation and a substr:
I did 10 iterations of function1 and function2. The results:Code:#include <string>
#include <afxtempl.h>
int dummy_var = 0;
void function1(const char*Data)
{
CString strData = Data;
for ( int i = 0; i < 1000; ++i)
strData += strData.Mid(0, 500);
}
void function2(const char*Data)
{
std::string strData = Data;
for ( int i = 0; i < 1000; ++i)
strData += strData.substr(0, 500);
}
Adding reserve:Quote:
Time duration is as follow:
LenTime1 = 1390
LenTime2 = 1438
LenTime3 = 94
LenTime4 = 203
LenTime5 = 234
The times are now this:Code:void function2(const char*Data)
{
std::string strData = Data;
strData.reserve(1000000);
for ( int i = 0; i < 1000; ++i)
strData += strData.substr(0, 500);
}
To your point about reserve():Quote:
Time duration is as follow:
LenTime1 = 1360
LenTime2 = 15
LenTime3 = 94
LenTime4 = 172
LenTime5 = 234
The reserve() is one of those functions that are usually not coded on the first cut of a program. It's when you find out how the string class is used and when bottlenecks occur, then the change to call reserve() is made. So how much memory to reserve() is not based on any hard numbers up front when you start coding, but on sheer experience when your program goes through the rigors.
Regards,
Paul McKenzie
I peform test on VC++ 7.1 compiler, and the CString class out peforms the std::string class on that version also.Quote:
Originally Posted by Paul McKenzie
Your results still showed CString out performing std::string.Quote:
Originally Posted by Paul McKenzie
On my own test, it shows CString has an even better improvement.
I also question whether your test is valid since you removed code I put in there that force the compiler not to optimize away the code.
Good try :p , but no cigar.Quote:
Originally Posted by Paul McKenzie
This is not a valid test, since you added the reserve code to the std::string function, but did not do the same logic for the CString function.
If I added the same logic to the CString function, you'll see CString still out peforms std::string.
Test the following valid code test:
The above test code shows the following results:Code:int dummy_var = 0;
const int SizeData = 512;
void function1(const char*Data)
{
CString strData = Data;
strData.GetBuffer (1000000);
strData.ReleaseBuffer();
for ( int i = 0; i < 1000; ++i)
strData += strData.Mid(0, 500);
dummy_var += strData[99];
}
void function2(const char*Data)
{
std::string strData = Data;
strData.reserve(1000000);
for ( int i = 0; i < 1000; ++i)
strData += strData.substr(0, 500);
dummy_var += strData[99];
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
const QtyTimesTest = 999;
DWORD StartTime, LenTime1=0, LenTime2=0;
char DummyData[SizeData+1];
memset(DummyData, 'x', SizeData);
DummyData[SizeData] = 0;
{
StartTime = GetTickCount();
for (int i = 0;i < QtyTimesTest;++i)
{
function1(DummyData);
}
LenTime1 += (GetTickCount() - StartTime);
}
{
StartTime = GetTickCount();
for (int i = 0;i < QtyTimesTest;++i)
{
function2(DummyData);
}
LenTime2 += (GetTickCount() - StartTime);
}
{
StartTime = GetTickCount();
for (int i = 0;i < QtyTimesTest;++i)
{
function2(DummyData);
}
LenTime2 += (GetTickCount() - StartTime);
}
{
StartTime = GetTickCount();
for (int i = 0;i < QtyTimesTest;++i)
{
function1(DummyData);
}
LenTime1 += (GetTickCount() - StartTime);
}
#ifdef _DEBUG
printf("You're not running release version!!!\nTest is only valid in release version.\n");
#else
printf("Time duration is as follow:\n\
CString = %li\n\
std::string = %li\n",
LenTime1, LenTime2);
#endif
if (!dummy_var) printf("dummy %i", dummy_var);
system("pause");
return nRetCode;
}
Time duration is as follow:
CString = 9140
std::string = 39266
This shows the CString out performming std::string by a ratio of 4 to 1.
The CSting class is 400% faster even when using the reserve method.
I also ran the above code on VC++ 7.1, and I got the following results:
Time duration is as follow:
CString = 11032
std::string = 18828
This show that on 7.1 the std::string class has improve peformance compare to VC++ 6.0, but CString still does about 70% better.
By how much? Not 4 to 1 or 10 to 1 as your test shows. They are virtually identical when I run the same tests. Such vast differences in tests should be explained before proclaiming which is faster or slower.Quote:
Your results still showed CString out performing std::string.
Regards,
Paul McKenzie
I don't put too much wait on your test, since you've removed some of the code that insures the compiler does not optimize away some of the code.Quote:
Originally Posted by Paul McKenzie
That might be why you're getting different results.
Did you run the last test code I posted? (without removing validation code)
It shows a ratio of 4 to 1. CString is 400% faster on that test.
OK....
I just ran the same exact executable on a Windows 2000 machine an it gave a result similer to what you posted.
Time duration is as follow:
CString = 11843
std::string = 14016
On my Windows XP machine, the CString class seems to be much much faster then the std::string class.
So I guess the result will very from OS to OS, and from one computer to another.
In either case, CString is still doing much better.
So according to above results, if you code using CString instead of std::string your code peformance will be any where from 1000% to 30% faster then std::string.
I changed the order of what function is performed first. I did the std::string test before the CString test, and the timing is as follows:
I did not change any code -- all I did was run your latest example verbatim, and for the latest test above, changed the order of which function was done first (and also changed the output so that the timings don't get mixed up).Quote:
Time duration is as follow:
CString = 6860
std::string = 6809
And if I did remove code, what would that matter? Tests should hold up no matter what code I tried, so long as both are similar. Also, all of the tests that I've run, except for the code where I added the reserve() for the std::string, is the code you posted as-is.
Regards,
Paul McKenzie
I find that hard to believe. NOT calling you a liar. I just don't think your code is getting compiled right, or something is wrong with your computer/OS.Quote:
Originally Posted by Paul McKenzie
What OS are you testing on, and does it have the latest updates?
Do you have the latest SDK for your compiler?
Can you email me your executable? ([email protected])
I changed the code around so that std::string comes first, and I still get similar results:
Time duration is as follow:
CString = 6780
std::string = 22391
According to what you posted before, you did modify the code. Unless what you posted is not the same as what you tested.Quote:
Originally Posted by Paul McKenzie
It does make a difference. The compiler can complete optimize away code that it determines it's not being used.Quote:
Originally Posted by Paul McKenzie
If you call a function, and nothing gets returns or saved from that function, the compiler can optimize away the function call.
Even if the code is similar, the compiler can optimize away one function, and not the other, or optimize away both functions, in which case the results would be numbers that are similar. (Like the results you posted)
Another advantage is that you can use std::string and std::wstring simultaneously in the same program. I don't think there is a CWideString class that you could use in a non-Unicode program.Quote:
Originally Posted by Graham
Also, std::string is actually the template basic_string<char>, therefore you can change the allocator (if necessary), and basically do anything wrt character streams.
As far as the implicit conversion, my experience is that it causes more problems than it's supposed to solve. Try to figure out why you are getting weird conversions going on "behind your back" at run-time or resolve those "ambiguous function overload" compiler errors. This is for implicit conversions in general, and not really specific to CString.
Regards,
Paul McKenzie
I am now working on a Windows 2K machine, with Service Pack 6 installed for VC++ 6.0. Pentium 3, 1.2GHZ processor.
I'm just reporting what I'm getting when running your program. I e-mailed you the executable.
A difference of 4 or 10 to 1 is just too large of a difference. If there was this much difference, it could be easily explained in the code of both CString and std::string (i.e. std::string does this, while CString does that). Nothing strikes me in the code that I've seen in both CString and std::string that would have this difference. I've also never heard of others touting such differences in speed in CString vs. std::string. Minimal differences, yes, but not on the order of 4 or 10 fold.
As to the order of the functions -- maybe the difference is caching, who knows. But I have seen situations where timings were different, depending on which tests are done first.
Regards,
Paul McKenzie
I just ran the executable you emailed, me and I'm getting similar results to what you posted.
Either something is wrong with my compiler or your compiler.
Or your code is not the same as mine.
Can you post or email EXACTLY what you compile (Copy and Paste).
I compiled my code as a Win32 Console application with MFC support.
Is that how you compiled yours?
I compiled as a Win32 console program, using MFC in a shared DLL.
The way I set up my project is to have a Win32 console program, with no MFC support, and then just change the project settings to use the MFC shared libraries. Of course, you have to know what to include to get everything working.
Attached is the code that I used. Again, I would be very surprised (even shocked) if a commercial implementation of std::string (any implementation) were 4 to 10 times slower than CString, which is why I had to verify your claims.
Also, I was perusing the internet, and found some discussions on using GetBuffer()/ReleaseBuffer() to do the same as reserve(). According to what I've read, GetBuffer()/ReleaseBuffer() isn't documented to do the same as reserve(), and you're relying on undefined/undocumented behavior.
Regards,
Paul McKenzie
I ran the executables you sent me, and here are my results:
Quote:
For VC 6.0
Time duration is as follow:
CString = 13379
std::string = 13981
Regards,Quote:
For VC 7.1:
Time duration is as follow:
CString = 12638
std::string = 12769
Paul McKenzie
Ran the original program on my machine; Athlon 1.4GHz
VC 6.0, Release code, code generation for Pentium.
Time duration is as follow:
LenTime1 = 240 <<<< CString
LenTime2 = 160 <<<< std::string :confused:
LenTime3 = 150
LenTime4 = 181
LenTime5 = 220
Press any key to continue . . .
Not sure if someone find this interesting but I recently performed some performance tests for string concatenation on VS2005 Beta.
In outer_f() I called inner_f() outer_loop number of times.
In inner_f() I performed a concatenation inner_loop number of times.
The string that I concated was 20 characters long.
On my machine for:
outer_loop = 1000
inner_loop = 1000
std::string : 0.224415
std::vector : 0.275405
CString : 0.161216
For:
outer_loop = 100000
inner_loop = 10
std::string : 1.77802
std::vector : 3.74253
CString : 1.65125
For:
outer_loop = 10
inner_loop = 100000
std::string : 0.216147
std::vector : 0.220373
CString : 10.565
This was interesting for me:
1. I expected std::vector to perform better.
2. When using a large inner loop (many concatenations on the same string) the performance for CString drops dramatically. Cache issue?
Not claiming that my tests proofs anything particular. I just thought it was interesting to note how different they behaved.
Hope this was of some interest to someone
I compiled the test1.cpp file that Paul attached to his post. I'm running VC++ 7.1 on Windows 2000 Professional, SP4. I'm running a Pentium 4 3.4 GHz with 1GB of RAM.
Edit: I ran the test a couple more times.Code:Time duration is as follow:
CString = 1156
std::string = 1156
Looks like they're pretty close to me. std::string looks to be a bit ahead, but with a synthetic benchmark like this, that's too close to call.Code:Time duration is as follow:
CString = 1141
std::string = 1109
Time duration is as follow:
CString = 1141
std::string = 1093
Time duration is as follow:
CString = 1172
std::string = 1140
Time duration is as follow:
CString = 1157
std::string = 1140
I just compiled the program on a compiler at work (VC++ 6.0).Quote:
Originally Posted by Paul McKenzie
And ran the code on the same computer (Windows 2000 Professional).
I got the following results:
Time duration is as follow:
CString = 9156
std::string = 16125
Press any key to continue . .
CString still about twice as fast.
I've also had other experts from experts exchange peform the same test, and they've all come back with results that very from 40% to 400% increase CString peformance over std::string.
I have to conclude that either there's something wrong with your compiler, or you're not compiling the exact same code.
You may also have some third party STL libraries loaded on your computer that is causing the difference.
I compiled the code using ONLY VC++ 6.0 libraries.
I've also made similar test about three years ago on two different client work sites.
They all show similar results with VC++6.0 std::string having significant peformance problems compared to CString.
That looks like the results of running a debug version instead of a release compiled version.Quote:
Originally Posted by JohnW@Wessex
Try running the last code I posted, that has a debug compile directive, that makes sure you're getting results for release version.
How do you explain the others here who are having similar results to mine? They took the code I posted, compiled it, and saw no increase in the speed. I even took your executable you sent, and it showed minimial difference. Therefore the conclusion is not that I or others are doing something wrong.Quote:
Originally Posted by Axter
I have no other STL library running. It is VC 6.0 and that's it. For such a significant difference as you've stated, again, it could be relatively easy to explain if the code were examined between CString and std::string.Quote:
You may also have some third party STL libraries loaded on your computer that is causing the difference.
I compiled the code using ONLY VC++ 6.0 libraries.
I've also made similar test about three years ago on two different client work sites.
And there is no signigicant performance problem when myself, Bob Davis, or JohnW@Wessex ran the program, and they, including myself, are the only ones who have tested your code.Quote:
They all show similar results with VC++6.0 std::string having significant peformance problems compared to CString.
Regards,
Paul McKenzie
They're not running the last code I posted, which insures the results are release mdoe code.Quote:
Originally Posted by Paul McKenzie
So untill I see the results of that code, I can't really consider they're post.
At some stage, we can't keep checking for gremlins on our computers and force a "slow" std::string.
Did you take the code that I posted (test1.cpp) and run it? It seems that you did, but are still not in line with Bob's and mine. You can't just keep discounting everything as "user error".
Regards,
Paul McKenzie
I haven't try using your code, because the code I've seen you post is not setup right.Quote:
Originally Posted by Paul McKenzie
The fact that you're asking me this question, makes me think you're not using the right code.
And I'm not just going by my results. I'm also going by results of several other experts from the Experts-Exchange.
And I'm not just going by the results of one computer. I've compiled similar test to this on several different development computers from different clients and ran it in many different machines.
What is not set up right? Take the code, and run it. See what results you get.
I have taken your code, and again, I have posted those results. In no way was I getting 2, 3, 4, or more fold increase in std::string (and I've tried this on two computers, a Pentium 3 running W2K, and XP running on a Pentium 4)
Regards,
Paul McKenzie
Well, then that's why we're getting different results, which is what I suspected.Quote:
Originally Posted by Paul McKenzie
I'm not sure what code of yours you're talking about, so please post what code you think is valid again, and if it is valid, I'll run it.
Why is it that you can't use the following code, which is a valid test with correct parameters:
Code:int dummy_var = 0;
const int SizeData = 512;
void function1(const char*Data)
{
CString strData = Data;
strData.GetBuffer (1000000);
strData.ReleaseBuffer();
for ( int i = 0; i < 1000; ++i)
strData += strData.Mid(0, 500);
dummy_var += strData[99];
}
void function2(const char*Data)
{
std::string strData = Data;
strData.reserve(1000000);
for ( int i = 0; i < 1000; ++i)
strData += strData.substr(0, 500);
dummy_var += strData[99];
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
const QtyTimesTest = 999;
DWORD StartTime, LenTime1=0, LenTime2=0;
char DummyData[SizeData+1];
memset(DummyData, 'x', SizeData);
DummyData[SizeData] = 0;
{
StartTime = GetTickCount();
for (int i = 0;i < QtyTimesTest;++i)
{
function1(DummyData);
}
LenTime1 += (GetTickCount() - StartTime);
}
{
StartTime = GetTickCount();
for (int i = 0;i < QtyTimesTest;++i)
{
function2(DummyData);
}
LenTime2 += (GetTickCount() - StartTime);
}
{
StartTime = GetTickCount();
for (int i = 0;i < QtyTimesTest;++i)
{
function2(DummyData);
}
LenTime2 += (GetTickCount() - StartTime);
}
{
StartTime = GetTickCount();
for (int i = 0;i < QtyTimesTest;++i)
{
function1(DummyData);
}
LenTime1 += (GetTickCount() - StartTime);
}
#ifdef _DEBUG
printf("You're not running release version!!!\nTest is only valid in release version.\n");
#else
printf("Time duration is as follow:\n\
CString = %li\n\
std::string = %li\n",
LenTime1, LenTime2);
#endif
if (!dummy_var) printf("dummy %i", dummy_var);
system("pause");
return nRetCode;
}
See post #28. It is attached.
Regards,
Paul McKenzie
Copying and pasting your exact code, adding the <afxtempl.h> and <string> headers.
And my "include directories" when building are as follows:Quote:
Time duration is as follow:
CString = 2859
std::string = 2750
Press any key to continue . . .
So there are no hidden "STL" implementations being used (or even installed)Quote:
C:\Program Files\Microsoft Visual Studio\VC98\INCLUDE
C:\Program Files\Microsoft Visual Studio\VC98\MFC\INCLUDE
C:\Program Files\Microsoft Visual Studio\VC98\ATL\INCLUDE
Regards,
Paul McKenzie
I didn't even see that attachment before.Quote:
Originally Posted by Paul McKenzie
I just compiled it and ran it, and I got the the following results:
Time duration is as follow:
CString = 4594
std::string = 8328
Which still shows CString with a 2 to 1 peformance increase.
This is on a work computer Windows 200 Pro ServicePack 4
I ran a few times, some times std::string was faster, other times CString was faster, but in both cases, miminal difference. This makes me believe there is a cache issue involved here.Quote:
Originally Posted by Paul McKenzie
Regards,
Paul McKenzie
Quote:
Originally Posted by Paul McKenzie
Running the same tests with the VC 7.1 (with the improved STL code that ships with VC 7.1) this is the output:
Time duration is as follow:
LenTime1 = 94
LenTime2 = 94
LenTime3 = 94
LenTime4 = 93
LenTime5 = 110
Press any key to continue . . .
Then this needs more investigation, which I really can't do or have time to do at this moment.Quote:
Originally Posted by Axter
As stated in my last post, there are other factors (possibly caching) that are involved other than algorithmic/implementation related. Since others here have run the program and had results similar to mine, this is the only plausible reason (other than not having speed optimization turned on).
It would be good if someone could figure out why there are such vast time differences between what you're getting and others are getting here. Maybe a careful review of the CString/std::string code when concatenations are done may shed some light on this. Who knows, we may need an OS internals expert to pin down what's going on.
Regards,
Paul McKenzie
I did, with VC 7.1:Quote:
Originally Posted by Axter
Time duration is as follow:
CString = 2579
std::string = 2484
Press any key to continue . . .
Actually, I did run your code. The code that I compiled and posted the results of earlier was the test1.cpp file that Paul attached to message #28. It did have the release-mode check in place.Quote:
Originally Posted by Axter
Nope. It was definitely release version.Quote:
Originally Posted by Axter
No third party libraries either.
std::string is always faster.
Output from the new codeQuote:
Originally Posted by Axter
Time duration is as follow:
CString = 4036
std::string = 4627
Press any key to continue . . .
The original code shows std:string to be faster.
The new code shows CString to be faster.
Both sets of code compiled as Release versions.
:confused:
If you disable exception handling in the project settings...
Time duration is as follow:
CString = 4246 <<<< Increase
std::string = 4376 <<<< Decrease
Press any key to continue . . .