C++ 10 Feb 2011 18:24:56

C++ String Compare Performance

A performance comparison of the speed of various ways to compare strings in C++. In this test, all comparisons are of not-equal strings.

Idea from #C++ on QuakeNet, where we always advocate using std::string over various char* functions. I wondered what, if any, the penalty for doing so was.

Sources

Things Tested

  • a hand-written naive comparator loop; used as baseline
  • string == string
  • string == const char*
  • strcmp(const char*, const char*) == 0
  • strcmp(const char*, string.c_str()) == 0
  • strcmp(string.c_str(), string.c_str()) == 0
  • string.compare(string)
  • string.compare(const char*)
  • …and then the whole thing with different offsets.

Observations

  • clang++ beats or is on par with g++
  • The penalty for using wide strings on Windows is not nearly as bad as on Linux (and in some cases faster). I speculate two reasons for this: Windows wchar_t is 16 bit versus Linux’ 32bit, and Windows uses wchar_t all over so operations on it have been greatly optimized.

Linux: GNU g++ 4.4.1

  • Compiler: GNU g++ 4.4.1 -O3
  • Arch: Linux 2.6.27 x86_64, 2.66GHz Xeon, 8 GiB RAM

g++ 4.4.1 [i-1]stringrelativewide stringwide relativewstring / string
naive(char*,char*)705488641.001468792561.002.08
naive(string,string)706367921.001497690001.022.12
string == string1092084081.551632962161.111.50
string == char*1612056082.291923042481.311.19
strcmp(char*,char*) == 0701084640.991046910320.711.49
strcmp(char*,string.c_str()) == 0743682641.051119332080.761.51
strcmp(string.c_str(),string.c_str()) == 0700731120.991067400880.731.52
string.compare(string) == 01115228481.581673345601.141.50
string.compare(char*) == 01612812962.291923900561.311.19

g++ 4.4.1 [N-i-1]stringrelativewide stringwide relativewstring / string
naive(char*,char*)1024769281.001062524161.001.04
naive(string,string)1096584561.071083346481.020.99
string == string1286633361.261286783361.211.00
string == char*1566943521.532089493761.971.33
strcmp(char*,char*) == 01074132641.051203580481.131.12
strcmp(char*,string.c_str()) == 01106949521.081218470081.151.10
strcmp(string.c_str(),string.c_str()) == 01078617761.051200911041.131.11
string.compare(string) == 01400368321.371334729041.260.95
string.compare(char*) == 01557770001.522094268881.971.34

Linux: LLVM clang++

clang++ 2.9 (trunk 124900) [i-1]stringrelativewide stringwide relativewstring / string
naive(char*,char*)728806241.001096670481.001.50
naive(string,string)752988161.031664266721.522.21
string == string747538561.031657880961.512.22
string == char*1510959842.071911004481.741.26
strcmp(char*,char*) == 0699061040.961039620240.951.49
strcmp(char*,string.c_str()) == 0742833281.021105781601.011.49
strcmp(string.c_str(),string.c_str()) == 0698530480.961060187680.971.52
string.compare(string) == 0748327281.031743815521.592.33
string.compare(char*) == 01501023042.061911082881.741.27

clang++ 2.9 (trunk 124900) [N-i-1]stringrelativewide stringwide relativewstring / string
naive(char*,char*)1055433841.001076517121.001.02
naive(string,string)1106114401.051096010801.020.99
string == string1173460961.111282534641.191.09
string == char*1573049681.492080927041.931.32
strcmp(char*,char*) == 01073816001.021202882161.121.12
strcmp(char*,string.c_str()) == 01090431361.031220773841.131.12
strcmp(string.c_str(),string.c_str()) == 01078944241.021201372161.121.11
string.compare(string) == 01203402561.141583343281.471.32
string.compare(char*) == 01572303681.492080662961.931.32

Windows: MSVC++ 2010

  • Compiler: MSVC++ 2010 _SECURE_SCL=0
  • Arch: Windows 7 64 bit, 1.60GHz Core i7 Q720, 8 GiB RAM

VC++ 2010 [i-1]stringrelativewide stringwide relativewstring / string
naive(char*,char*)173101621.00186179621.001.08
naive(string,string)210689221.22202665691.090.96
string == string127528920.74185093800.991.45
string == char*216259361.25255605021.371.18
strcmp(char*,char*) == 0114050720.66118904580.641.04
strcmp(char*,string.c_str()) == 0141009700.81151774880.821.08
strcmp(string.c_str(),string.c_str()) == 0120422380.70111070500.600.92
string.compare(string) == 0129764020.75208462981.121.61
string.compare(char*) == 0209112961.21279349321.501.34

VC++ 2010 [N-i-1]stringrelativewide stringwide relativewstring / string
naive(char*,char*)96199661.00116949501.001.22
naive(string,string)95630980.9998931010.851.03
string == string152248001.58135993121.160.89
string == char*196735702.05178005321.520.90
strcmp(char*,char*) == 097376201.01124877701.071.28
strcmp(char*,string.c_str()) == 0113240821.18122061461.041.08
strcmp(string.c_str(),string.c_str()) == 0101105781.0593157700.800.92
string.compare(string) == 0146270481.52149937901.281.03
string.compare(char*) == 0207978562.16207104841.771.00

3 Responses to “C++ String Compare Performance”

  1. on 13 Sep 2011 at 18:51:09 1.Ayyappa said …

    Hai,

    Recently I also done an performance test on the same aspect.But your Performance check range(based on different envi) is relatively high.Can you please finalize the results in brief synopsis.(something like strcmp()-> which might use memcmp func is faster…).Please finalize a summary on this test.

  2. on 14 Sep 2011 at 09:50:49 2.Tino Didriksen said …

    Well, I am not very happy with this test. I can reliably reproduce the results, but the results are not what I would expect.

    string op== is horrendous. There is no way in my head that a sane implementation of that should be slower than strcmp(), yet it is. And the fact that it’s even slower when comparing to char* tells me they just let the buffer get silently converted to a string, then compare…which is crazy (but it is standard compliant).

  3. on 22 Sep 2011 at 01:51:15 3.Rodrigo said …

    I personally dislike not only the operator== overloading, but the C++ operator overloading in general. To me they hide way too much what is being done, and it’s easy to neglect optimizations.

Subscribe to the comments through RSS Feed

Leave a Reply

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Anti-spam image