Skip to content

Last updated:2026-10-12

C++ string SSO Performance Test

Today I want to ask you two questions:

1. Is there any difference in performance between the following lines of code?

std::string s1("hello world hel");
std::string s2("hello world helo");

2. What is sizeof(std::string)?

Let's explore these two questions together.

Since the answers to both differ between g++ (libstdc++) and clang (libc++), each is analyzed separately below.

1. g++ (libstdc++)

For the g++ source code, we take g++-10 as the example; see this GitHub link for the detailed code — here the core parts are listed.

https://github.com/gcc-mirror/gcc/blob/devel/omp/gcc-10/libstdc%2B%2B-v3/include/bits/basic_string.h#L171

template<typename _CharT, typename _Traits, typename _Alloc>
class basic_string {
  private:
    struct _Alloc_hider : allocator_type {
        pointer _M_p; // The actual data.
    };
      enum { __min_cap = 15 / sizeof(value_type) };
    _Alloc_hider    _M_dataplus;             //  8 bytes
    size_type __size_;                     //  8 bytes

    union {
            _CharT           _M_local_buf[_S_local_capacity + 1]; // 16 bytes 
            size_type        _M_allocated_capacity;                             // 8 bytes
    }; // 16 bytes
}; // 32 bytes

In the code above, the comments spell out in detail the bytes a string occupies (note: value_type is counted as char here, i.e. sizeof(value_type) = 1).

sizeof(string) = 8 + 8 + 16 = 32.

That is 8 bytes of ptr, 8 bytes of size, and a 16-byte union.

Performance-wise, SSO is implemented here: the local buffer stores up to 15 characters, and once there are more than 15 characters the data is allocated on the heap. I wrote a benchmark to compare the performance.

  • The short-string test input is "hello world hel", 15 characters in total.
  • The long-string test input is "hello world helo", 16 characters in total.
std::string s1("hello world hel");
std::string s2("hello world helo");

As you can see, the performance gap is huge — a single character makes this much difference for std::string!

At its core, this is still the SSO local buffer mentioned earlier.

Benchmark: https://quick-bench.com/q/s7pvDB_SwQyDCcZk50odAaYIzMc

gcc short long

2. clang++ (libc++)

Likewise, we take llvm-14 as the example; if you want the complete code, follow the GitHub link below — here the core parts are excerpted.

https://github.com/llvm/llvm-project/blob/release/14.x/libcxx/include/string#L765

template<class _CharT, class _Traits, class _Allocator>
class basic_string {
  private:
    struct __long {
        size_type __cap_;               // 8 bytes
        size_type __size_;              // 8 bytes
        pointer   __data_;              // 8 bytes
    };

        enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ?
                      (sizeof(__long) - 1)/sizeof(value_type) : 2};

    struct __short {
        union {
            unsigned char __size_;      // 1 bytes
            value_type __lx;            // 1 bytes 
        };                              // 1 bytes
        value_type __data_[__min_cap];  // 23 bytes
    };                                  // 24 bytes

        union __ulx {
            __long __lx;        // 24 bytes
            __short __lxx;  // 24 bytes
        }; // 24 bytes
}

In the code above, the comments spell out in detail the bytes a string occupies (note: value_type is counted as char here, i.e. sizeof(value_type) = 1).

sizeof(string) equals the size of the union, and this union is 24 bytes, so it is 24.

As for SSO, the local buffer holds no more than 22 characters; beyond 22 characters the data is allocated on the heap.

So when we run on clang the same test code we used for gcc, we get rather different results: the long string performs about the same as the short one. The reason is that the gcc test cases are all within 22 characters — all short strings.

Benchmark: https://quick-bench.com/q/nmLMqQZ31cmWBbbIFr2nHN2JL1k

llvm short long no

When we test genuinely long and short strings, performance changes noticeably, with the trend matching gcc.

  • The short-string test input is "hello world hello worl", 22 characters in total.
  • The long-string test input is "hello world hello world", 23 characters in total.

Benchmark: https://quick-bench.com/q/ujtMrtotEi6RrpfMDJ1UcSLFIJE

llvm short long

Comments