-10

I guess it is not a secret std::string is much slower than C string (in most of all aspects: allocation, comparison, search):

// alloc
malloc/memcpy : 1.972 secs
std::string : 2.259 secs
// compare
strcmp : 1.319 secs
std::string.compare : 15.802 secs
// search
strstr : 5.045 secs
memmem : 1.345 secs
std::string.find : 7.774 secs

So my question here would be not how to fix it but why std::string is slow (what STL did make wrong or am I wrong)? This slowness make std::string almost useless. So usage of std::string as a key in associative containers makes the things even worse (since comparisons are required when insert/search).

Just to note the only exception is std::string is copied very fast - because it is ref-counted (thought GCC 5 thinks to remove that).

Attaching my benchmark code to: https://drive.google.com/file/d/0B_jw6pBAvP6bSEtmLTA4RU5zZ00/view?usp=sharing

The code is build using:

g++ -O2 -g perf_cstr_vs_std.cpp -o perf_cstr_vs_std

Build/run environment:

RedHat6 VM + gcc 4.4.7
  • 6
    If you don't show your test code you will get down-voted. Most likely scenario is your test-cases are not testing the same thing. – Richard Critten Aug 04 '17 at 10:24
  • 2
    It is unclear what you are comparing. std::string is slow if you do stuff with it that you wouldn't do with a "c-string" (whatever that is.) But note that many operations involving strings (getting substrings for example) involve creating new string objects that allocate their own memory and hold copies of data. The new [`std::string_view`](http://en.cppreference.com/w/cpp/string/basic_string_view) fixes some of those problems. – juanchopanza Aug 04 '17 at 10:27
  • 2
    Are you building with optimizations enabled? Otherwise your numbers are meaningless. Also, please provide a [mcve]. – Jesper Juhl Aug 04 '17 at 10:27
  • 1
    One common cause of performance discrepancies, though I do not know your test setup, is that the C++ standard library tends to rely heavily on inlining and may therefore degenerate outside of optimized builds where these are disabled. This is not typically a major problem for shipping software but can force the use of otherwise undesirable heightened optimization levels during development in order to meet timing constraints. – doynax Aug 04 '17 at 10:35
  • Hi All. I'm sorry - I forgot to attach my code and paste the command I used to build it. Surely I built it with optimization (O2). And obviosly I don't use std::string because of performance issues. My question here was not "what to do" but why std::string is slow and will it ever perform equally to C string. – Alexander Maximov Aug 04 '17 at 11:00
  • 1
    for what it's worth, I put your code on VS2017 (with a few porting tweaks) and get similar percentages for the alloc (.616/.708) which is about 15% overhead roughly matching yours. My compare (3.473/3.708) is about 7% overhead which is dramatically different that yours... but it's clear from the output that the code you posted doesn't match the output above so you might look at what's going on different there. IMO those small performance differences are worth the convenience... – mark Aug 04 '17 at 12:34
  • Hi Mark, thanks for your feedback. Obviously timings will be different on different computers. I tried on my RedHat6 VM. Seems like Windows STL is implemented another way than linux libstdc++. And I like std::string convenience but the performance is unacceptable for me. – Alexander Maximov Aug 04 '17 at 13:18

2 Answers2

1

All the strings used here are 1000 repetitions of 'a' or 'A' which might not give an accurate estimate of the timings.

C++: 201103, GCC: 4.9.2

Test operation numIters: 10000000 numRuns: 1 numItems: 1000

Run 1

malloc/memcpy : 1.512 secs

realloc/memcpy : 1.634 secs

std::string : 1.956 secs

why? refcounting??? the 5.x.x used at work doesn't do this afaik.

strcmp : 10.780 secs

std::string.compare(const char* s) : 5.346 secs

OK, my version of compare is faster than strcmp ...

  static int
  compare(const char_type* __s1, const char_type* __s2, size_t __n)
  { return __builtin_memcmp(__s1, __s2, __n); }

so std::string has to do a strlen before it can call this, but then it can be more efficient afterwards.

std::string == std::string : 2.356 secs

strncmp : 10.796 secs memcmp : 2.355 secs

std::string.compareN : 5.453 secs

strstr : 4.027 secs

std::string.find : 6.061 secs

Find could be implemented more efficient, C++17 gets Boyer-Moore-Horspool string searching algorithm.

Surt
  • 15,501
  • 3
  • 23
  • 39
-1

Quite interesting results. I've re-run the benchmark on 4.8.2 20140120 and got:

strcmp : 1.938 secs
std::string.compare(const char* s) : 1.842 secs
std::string == std::string : 1.225 secs
strncmp : 2.660 secs
memcmp : 1.182 secs
std::string.compareN : 1.711 secs

strstr : 5.854 secs
memmem : 1.187 secs
std::string.find : 14.363 secs 

So std::string behaves different. On ref-counting see Is std::string refcounted in GCC 4.x / C++11?