Copy-on-write string performance

Since I’ve started using Qt, I loved the “implicit sharing” concept it uses for it’s strings and container types. It become so much easier to pass these data around. I wasn’t aware that some STL implementations have copy-on-write semantics for strings as well. When I saw some recommendations for std::string on Stack Overflow, I’ve decided to check out the implementation in GCC and discovered that it indeed does some reference counting.

So the next step was comparing the implementations. I wrote a little program today to check how QString and std::wstring compare in terms of copy-on-write performance. Since QChar is 2 bytes and wchar_t is 4 bytes on my machine, it wouldn’t be completely fair comparison, so I’ve included also std::string. The results were quite surprising for me. STL does almost always better, but for some reason I wasn’t able to make not dereference the string on read-only operations.

wchar_t* QString std::wstring std::string

Read

0 ms

0 ms

2143 ms

2224 ms

Write

0 ms

5588 ms

2621 ms

2570 ms

Copy

1618 ms

601 ms

116 ms

117 ms

Copy + read

-

601 ms

6161 ms

5079 ms

Copy + write

-

11036 ms

6822 ms

6843 ms

Copy + append

-

5801 ms

4650 ms

3482 ms

The table shows times in milliseconds for 10000000 repeated operations on a 200-character long string.

  • Read” just reads the string one character at a time, using the default [] operator. I’ve tried hard to find a cheaper way to do this for STL strings, but I failed (I wasn’t interested in using s.data() and then working with the primitive array, I wanted to work with the object directly).
  • Write” writes to all characters of the string, again one character at a time.
  • Copy” assigns one string to another, using the default = operator for string classes and memcpy for wchar_t*.
  • Copy + read” is the same as “Copy”, followed by “Read” performed on the copy.
  • Copy + write” is the same as “Copy”, followed by “Write” performed on the copy.
  • Copy + append” is again the same as “Copy”, followed by appending a short string to the copy.

I guess I should note that this wasn’t meant to be a generic benchmark of the string classes. I just wanted to know performance details about the copy-on-write implementations in them. The conclusion for me is that the STL strings in GCC are better than I always thought, but the fact that they dereference the data on read-only operations is not very nice.