Search
Write a publication
Pull to refresh

Comments 33

Тезисно:
— Для использования компактных строк от программиста не требуется ничего, кроме запуска приложения под джавой 9.
— Для русского языка компактные строки не дадут ни байта выигрыша.

М-да…

Скажите, я правильно понял: внутри компактные строки хранят utf-8? А каков проигрыш в производительности при использовании строк с кириллицей — ведь их придется кодировать-декодировать при любых манипуляциях? А каков будет «выигрыш» при использовании, скажем, строк индийских символов или китайских иероглифов, где один символ может кодироваться в urf-8 тремя, четырьмя, а то и пятью байтами?
Ай, моя плохой, не заметил, что там utf-16:
Другими словами, эта функция заменяет значение в массиве char (где каждый элемент использует 2 байта) байтовым массивом с дополнительным байтом для определения кодировки (Latin-1 или UTF-16).

Вопрос снимается, голова пеплом посыпается.
Остается не очень понятно, зачем под битовый флажок отвели целый байт, ну да ладно.
Надеюсь не сильно перевру если опишу историю кратко — JEP делал не безызвестный Алексей Шипилёв — и что согласно профилям приложений который активно работали с не latin-1 строками (имена не назывались, но представьте себе региональные социальные сети) — и даже в их случае количество latin-1 строк было достаточно высокое (не 50%, но и не 10%). Среди прочего это и внутри vm вещи — имена классов и т.п.

Почему не бит — вопрос в том как его хранить с кем его есть — опять же — бенчмарки показали, что так (с флагом) будет лучше.
Остается не очень понятно, зачем под битовый флажок отвели целый байт, ну да ладно.
А как вы себе представляете размещение отдельного бита в памяти?
Отдельный бит можно запихать в уже существующее поле флагов, если таковое есть. Если нет — то остается еще вариант разместить флаг в младшем бите какого-нибудь адреса или ссылки. Адреса, выделяемые менеджером памяти, как правило, выровнены на границу слова, а то и 16 байт — т.е. младшие один-два-три бита в адресе всегда нулевые. Этим можно воспользоваться.
Отдельный бит можно запихать в уже существующее поле флагов, если таковое есть.

Можно, посмотрели, это всё не взлетело. Кроме того, добавление байтового поля реально не увеличило затрат памяти из-за уже существующего до этого выравнивания. Подробности можно увидеть по ссылка в этом комментарии.

Оффтопик.

один символ может кодироваться в urf-8 тремя, четырьмя, а то и пятью байтами


Разве где-то сейчас используется UTF-8 с символами больше 4 байт?

Вроде в RFC 3629, который является официальным стандартом, указано, что «In UTF-8, characters from the U+0000..U+10FFFF range are encoded using sequences of 1 to 4 octets». И символы за пределами этого range запрещены («Restricted the range of characters to 0000-10FFFF»).

Но в предыдущей (давно устаревшей) версии стандарта (rfc2279) были возможны символы, требующие до 6 байт.

Или я что-то упускаю?
Нет, не упускаете.
Это у меня в голове сведения устаревшие.
Господи, почему в 2к18 ещё не все переехали на UTF-8?

Нет, и не переедут. Это поломает существующее API

Думаю имелся ввиду Юникод вообщем, а не конкретно UTF-8.
На «Юникод вообщем» Java переехала с рождения.
UFO landed and left these words here
А что подходит?
UTF-16 со своими суррогатными парами даёт ложную надежду, но всё равно не позволяет бегать по индексу. Для того, чтобы обращаться по индексу к строке с эмодзи нужна отдельная функция. Строка — не массив, в любой кодировке.
UFO landed and left these words here

Utf8 совместим с ascii, utf16 нет.
Для ascii строк он в два раза выгоднее, чем utf16.
У utf8 нет проблемы с BE/LE.
Оба не позволяют индексировать строку, в отличие от utf32.
Так что не все так однозначно.

Забыли упомянуть о том, что UTF-8 совместим с null-terminated представлением строк (к примеру, в C), а остальные нет
Суть в том, что UTF-32 тоже не позволяет индексировать строку. Ну или я не понимаю, как индексировать эмодзи с флагом цвета кожи и пола; как индексировать флаг Англии (который на каких-то системах — 7 символов, а на каких-то распарсился в 1 флаг). В итоге часто встречаю в современных мессенджерах обрезку посередине, что не красиво, но всем пофигу, т.к. верят в непогрешимость UTF-16 (который ворвался в стандарты как UCS-2).
P.S. хабр вообще порезал сообщение, встретив символ этого флага (ну или firefox плохо закодировал): emojipedia.org/flag-for-england

Максимальное значение одного символа — 0x10FFFF. Это около 21 бит. Следовательно в кодировке utf32 каждый символ занимает вмещается в 4 байта, и индексация вполне работает.

Есть еще суррогатные пары. Это когда, скажем, буква Ё передается двумя символами: модифицирующий символ «две точки над буквой» и собственно сама буква Е. Даже в русском языке суррогатными парами можно выразить аж две буквы (Ё и Й), а есть языки, где вообще половина символов может быть суррогатами.
Это называется «составные символы», а не «суррогатные пары».
Я полагаю вы ошиблись и имели ввиду UTF-*, а не конкретно UTF-8?
Так как для разных задач используются разные UTF.

  • UTF-8 — выгодно хранить текст. Совместима с ascii, нормально работает в старых программах и компиляторах как нуль-терминальная строка.
  • UTF-16 — удобно использовать в программировании, так как размер массива, как правило, равен количеству символов, по крайней мере для латинского/кириллического алфавита и спецсимволов.
  • UTF-32 — можно использовать как массив символов, удобно в работе с обработкой текста (поиском и т.д).


Вот поиск как раз одинаково хорошо работает в любой кодировке…
Павел, я не написал, что поиск по другим кодировкам как то плохо работает. Писать софт для обработки текста (в том числе и поиска) удобнее/проще, для кодировки где элемент массива это всегда отдельный символ.
Господи, почему в 2к18 ещё не все переехали на UTF-8?

В Джаве есть класс String. Его методы используются в большом количестве софта. В частности используется метод charAt(int index). В частности он используется внутри циклов. Если перейти на utf-8 (что в общем прекрасная идея) — алгоритмическая сложность charAt станет линейной, а сложность методов, в которых есть циклы — квадратичной. На это пойти никак нельзя.

Суть данного треда как раз в том, что сложность charAt константна только для 1-байтных кодировок и UCS-* (который использовался, когда зарождались Java и WinNT), но сейчас они все [втихую] переехали на UTF-*, а Unicode ввёл emoji. И уже у всех charAt должен быть линейным, а у кого не так, тот заблуждается.
Суть данного треда как раз в том, что сложность charAt константна только для 1-байтных кодировок

А суть моего комментария в том, что charAt возвращает не codePoint а значение типа char, которое берётся прямиком из массива типа char, который находится под капотом у строки )). И куча народу этим пользуется. И ломать код этих людей нельзя, хотя он, возможно и не вполне корректный.

Объем статьи, конечно, поражает. Для тех кто хочет узнать об этом чуть больше, есть прекрасный доклад от Алексея Шипилёва.
Странно, что раньше не ввели. Жду, когда будет перегрузка операторов, constexpr, setter/getter, checked arithmetics, function purity level и тд
Получается, что если в «схлопнутую» строку добавить utf8, то размер новой строки = 2 размера старой + новый символ?

Если добавить любой символ, который не входит в latin1.

Sign up to leave a comment.