Ця відповідь дає хороший огляд високого рівня оптимізації коротких рядків (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
заголовок ви можете знайти тут , я зараз його перевіряю :)