Ця відповідь дає хороший огляд високого рівня оптимізації коротких рядків (SSO). Однак я хотів би більш детально дізнатися, як це працює на практиці, зокрема в реалізації libc ++:
Наскільки короткою повинна бути рядок, щоб мати право на отримання SSO? Це залежить від цільової архітектури?
Як реалізація розрізняє короткі та довгі рядки під час доступу до рядкових даних? Це так просто,
m_size <= 16чи це прапор, який є частиною іншої змінної члена? (Я думаю, щоm_sizeце може бути використано для зберігання рядкових даних).
Я задав це питання спеціально для libc ++, оскільки я знаю, що він використовує SSO, це навіть згадується на домашній сторінці libc ++ .
Ось кілька спостережень після перегляду джерела :
libc ++ може бути складено з двома дещо різними схемами пам'яті для класу string, цим регулюється _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заголовок ви можете знайти тут , я зараз його перевіряю :)