Этот ответ дает хороший общий обзор оптимизации коротких строк (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
макетов памяти в других реализациях стандартной библиотеки.
string
заголовок здесь , я проверяю его в данный момент :)