При написании пользовательского строкового класса, который хранит UTF-8 внутренне (для сохранения памяти), а не UTF-16 с нуля можно ли в какой-то мере кэшировать связь между смещением байта и смещением символа для повышения производительности, когда приложения используют класс со случайным доступом?
Использует ли Perl такой тип кэширования смещения символов для отношения смещения байта? Как строки Python работают внутри?
Как насчет Objective-C и Java? Используют ли они UTF-8?
ИЗМЕНИТЬ
Обнаружена эта ссылка на Perl 5 с использованием UTF-8:
"$ flag = utf8:: is_utf8 (STRING)
(Поскольку Perl 5.8.1) Проверьте, является ли STRING внутри UTF-8 внутренне. Функционально то же, что и Encode:: is_utf8(). "
На странице
http://perldoc.perl.org/utf8.html
ИЗМЕНИТЬ
В приложениях, которые я имею в виду, строки имеют 1-2K XML-строфы в потоке XMPP. Около 1% сообщений будет ожидать, что я ожидаю до 50% (по количеству символов) значений Unicode > 127 (это XML). На серверах сообщения проверяются по правилам и маршрутизируются условно на небольшое (символьное количество) подмножество полей. Серверы - это коробки Wintel, работающие в ферме. В клиентах данные поступают и передаются в набор инструментов пользовательского интерфейса.
ИЗМЕНИТЬ
Но приложение неизбежно эволюционирует и хочет сделать некоторый произвольный доступ. Может ли производительность удариться, когда это произойдет, будет сведено к минимуму: мне также было интересно, существует ли более общий дизайн класса, например, управляет b-деревьями смещения смещения символа ↔ byte для больших строк UTF8 (или какой-либо другой алгоритм, который считается эффективным в общем случае.)
Perl различает строки Unicode и non-Unicode. Строки Unicode реализуются с использованием UTF-8 внутренне. Не-Unicode не обязательно означает 7-битный ASCII, хотя он может быть любым символом, который может быть представлен в текущей локали в виде одного байта.
Строки Java являются внутренними UTF-16:
A String представляет строку в формате UTF-16, в которой дополнительные символы представлены суррогатными парами (дополнительную информацию см. в разделе "Представления символов Юникода в классе символов" ). Значения индекса относятся к единицам кода char, поэтому дополнительный символ использует две позиции в строке.
Я думаю, что ответ: в общем, на самом деле это не стоит пытаться это сделать. В вашем конкретном случае, возможно.
Если большинство ваших символов являются обычными ASCII, и у вас редко есть последовательности UTF, тогда может стоить создать какую-то разреженную структуру данных с смещениями.
В общем случае каждый отдельный символ может быть не-ASCII, и у вас может быть много задержек для хранения. В самом деле, самым общим случаем было бы сделать строку байтов, которая точно равна вашей строке символов Юникода, и каждое значение байта будет смещением следующего символа. Но это означает один общий байт на символ и, следовательно, чистую экономию только одного байта за символ Юникода; вероятно, не стоит усилий. И это означает, что индексирование в вашу строку теперь является операцией O (n), когда вы выполняете эти смещения и суммируете их, чтобы найти фактический индекс.
Если вы хотите попробовать разреженную структуру данных, я предлагаю массив пар значений, первое значение является индексом в строке Юникода символа, а второе - индексом в последовательности байтов, где это персонаж фактически появляется. Затем после каждой escape-последовательности UTF8 вы должны добавить два значения, чтобы найти следующий символ в строке. Наконец, при указании индекса на символ Unicode ваш код может выполнять двоичный поиск этого массива, чтобы найти наивысший индекс в разреженном массиве, который меньше запрошенного индекса, а затем использовать его для поиска фактического байта, который представляет начало желаемого символа.
Если вам нужно сохранить память, вам может потребоваться использовать библиотеку сжатия данных. Slurp в строках Unicode как полный Unicode, затем сжимайте их; затем, чтобы индексировать строку, сначала вы разжимаете эту строку. Это действительно спасет память, и будет легко и быстро получить код правильно, чтобы он работал; но это может привести к слишком большим нагрузкам на процессор, чтобы быть разумным.