在std :: string的上下文中,首字母缩略词SSO的含义

在关于优化和代码风格的C ++问题中 ,有几个答案在优化std::string拷贝的上下文中引用了“SSO”。 在这种情况下,SSO意味着什么?

显然不是“单一登录”。 “共享字符串优化”,也许?

背景/概述

自动变量(“来自堆栈”,这是你创建的变量,而不调用malloc / new )的操作通常比涉及免费存储(“堆”,这是使用new创建的变量)的速度快得多。 但是,自动数组的大小在编译时是固定的,但是自由存储的数组大小不是。 此外,堆栈大小是有限的(通常是几个MiB),而免费存储只受限于系统的内存。

SSO是短/小字符串优化。 一个std::string通常将该字符串存储为指向免费存储(“堆”)的指针,这会给出类似的性能特征,就像调用new char [size] 。 这可以防止对于非常大的字符串的堆栈溢出,但是可能会更慢,尤其是对于复制操作。 作为一个优化, std::string许多实现创建一个小的自动数组,类似char [20] 。 如果你有一个20个字符或者更小的字符串(给定这个例子,实际的大小会有所不同),它会直接把它存储在那个数组中。 这样就避免了需要调用new的功能,这会加快速度。

编辑:

我并不期待这个答案是如此受欢迎,但是既然如此,让我给出一个更现实的实现,但是我从来没有真正阅读过任何SSO的实现。

实施细节

std::string至少需要存储以下信息:

  • 尺寸
  • 能力
  • 数据的位置

大小可以存储为std::string::size_type或指向结束的指针。 唯一的区别是当用户调用size时是否需要减去两个指针,或者是否在用户调用end时将size_type添加到指针。 容量也可以以任何方式存储。

你不支付你不使用的东西。

首先,考虑基于我上面概述的天真实施:

 class string { public: // all 83 member functions private: std::unique_ptr<char[]> m_data; size_type m_size; size_type m_capacity; std::array<char, 16> m_sso; }; 

对于64位系统,通常意味着std::string每个std::string有24个字节的“开销”,加上另外16个用于SSO缓冲区(由于填充要求,16个而不是20个)。 存储这三个数据成员加一个本地字符数组是没有意义的,就像我简化的例子。 如果m_size <= 16 ,那么我将把所有的数据放在m_sso ,所以我已经知道容量了,我不需要指向数据的指针。 如果m_size > 16 ,那么我不需要m_sso 。 我需要所有这些绝对没有重叠。 没有空间的智能解决方案看起来更像这样(未经测试,仅用于示例目的):

 class string { public: // all 83 member functions private: size_type m_size; union { class { // This is probably better designed as an array-like class std::unique_ptr<char[]> m_data; size_type m_capacity; } m_large; std::array<char, sizeof(m_large)> m_small; }; }; 

我假设大多数实现看起来更像这样。

SSO是“小字符串优化”(Small String Optimization)的缩写,是一种将小字符串嵌入到字符串类的主体中而不是使用单独分配的缓冲区的技术。