Этот ответ дает хороший общий обзор оптимизации коротких строк (SSO). Однако я хотел бы узнать более подробно, как это работает на практике, особенно в реализации libc++:
Насколько короткой должна быть строка, чтобы претендовать на SSO? Это зависит от целевой архитектуры?
Как реализация различает короткие и длинные строки при доступе к строковым данным? Это так же просто, как
m_size <= 16
или это флаг, который является частью какой-то другой переменной-члена? (Я представьте, чтоm_size
или его часть также может быть использована для хранения строковые данные).
Я задал этот вопрос специально для libc++, потому что я знаю, что он использует SSO, это даже упоминается на libc++ домашней странице.
Вот некоторые наблюдения после просмотра источника:
libc++ может быть скомпилирован с двумя немного разными макетами памяти для строкового класса, это регулируется флагом _LIBCPP_ALTERNATE_STRING_LAYOUT
. Оба макета также различают машины с прямым порядком байтов и байтов с обратным порядком байтов, что дает нам в общей сложности 4 различных варианта. В дальнейшем я приму "нормальную" компоновку с прямым порядком байтов.
Предполагая далее, что size_type
составляет 4 байта, а value_type
равен 1 байту, это то, как первые 4 байта строки будут выглядеть в памяти:
// short string: (s)ize and 3 bytes of char (d)ata
sssssss0;dddddddd;dddddddd;dddddddd
^- is_long = 0
// long string: (c)apacity
ccccccc1;cccccccc;cccccccc;cccccccc
^- is_long = 1
Поскольку размер короткой строки находится в старших 7 битах, при доступе к ней ее необходимо сместить:
size_type __get_short_size() const {
return __r_.first().__s.__size_ >> 1;
}
Аналогично, метод получения и установки емкости длинной строки использует __long_mask
для обхода бита is_long
.
Я все еще ищу ответ на свой первый вопрос, то есть какое значение __min_cap
, емкость коротких строк, примет для разных архитектур?
Другие реализации стандартной библиотеки
Этот ответ дает хороший обзор макетов памяти std::string
в других реализациях стандартной библиотеки.