Внутренние классы String - кэширование смещения символа к байтовому отношению при использовании UTF-8

1

При написании пользовательского строкового класса, который хранит 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 (или какой-либо другой алгоритм, который считается эффективным в общем случае.)

  • 2
    Проблема, которую я вижу, заключается в том, что если кэш достаточно большой, чтобы быть полезным, он также будет достаточно большим, чтобы в значительной степени полностью компенсировать память, полученную при использовании UTF-8 вместо UTF-16. Если вы собираетесь использовать «мало памяти», сосредоточьтесь на низком использовании памяти, а не на скорости.
  • 0
    Зачем вам нужно экономить память? Вы делаете это на устройстве с ограниченной памятью? У вас есть несколько мегабайт строковых данных?
Показать ещё 3 комментария
Теги:
utf-8

3 ответа

2
Лучший ответ

Perl различает строки Unicode и non-Unicode. Строки Unicode реализуются с использованием UTF-8 внутренне. Не-Unicode не обязательно означает 7-битный ASCII, хотя он может быть любым символом, который может быть представлен в текущей локали в виде одного байта.

  • 0
    Хм ... Кто-нибудь хочет уточнить ...? Какую оптимизацию имеет Perl, если есть?
  • 0
    Хорошо, посмотрев на внутренние компоненты кода C на Perl, выяснилось, что он имеет концепцию курсоров для доступа к строкам UTF8 и измерения количества символов между двумя курсорами путем проверки. Хотя эти курсоры, конечно, являются C-указателями в Perl C-коде. Кажется, нет никакого упоминания о других типах доступа в UTF8, кроме указателей. Итак, в заключение, я не вижу оснований думать из кода Perl, что класс-оболочка UTF8 в Perl-esque в C # или Java может предложить более высокую производительность, чем байтовый массив и байтовый индекс. Если больше никого не нужно добавлять, я думаю, что я здесь.
Показать ещё 1 комментарий
1

Строки Java являются внутренними UTF-16:

A String представляет строку в формате UTF-16, в которой дополнительные символы представлены суррогатными парами (дополнительную информацию см. в разделе "Представления символов Юникода в классе символов" ). Значения индекса относятся к единицам кода char, поэтому дополнительный символ использует две позиции в строке.

java.lang.String

  • 0
    это вопрос Perl, а не Java
  • 1
    Оригинальный плакат спросил: «А как насчет Objective-C и Java? Они используют UTF-8 для внутреннего использования?» Этот вопрос отмечен на 4 разных языках. Это не просто вопрос Perl.
1

Я думаю, что ответ: в общем, на самом деле это не стоит пытаться это сделать. В вашем конкретном случае, возможно.

Если большинство ваших символов являются обычными ASCII, и у вас редко есть последовательности UTF, тогда может стоить создать какую-то разреженную структуру данных с смещениями.

В общем случае каждый отдельный символ может быть не-ASCII, и у вас может быть много задержек для хранения. В самом деле, самым общим случаем было бы сделать строку байтов, которая точно равна вашей строке символов Юникода, и каждое значение байта будет смещением следующего символа. Но это означает один общий байт на символ и, следовательно, чистую экономию только одного байта за символ Юникода; вероятно, не стоит усилий. И это означает, что индексирование в вашу строку теперь является операцией O (n), когда вы выполняете эти смещения и суммируете их, чтобы найти фактический индекс.

Если вы хотите попробовать разреженную структуру данных, я предлагаю массив пар значений, первое значение является индексом в строке Юникода символа, а второе - индексом в последовательности байтов, где это персонаж фактически появляется. Затем после каждой escape-последовательности UTF8 вы должны добавить два значения, чтобы найти следующий символ в строке. Наконец, при указании индекса на символ Unicode ваш код может выполнять двоичный поиск этого массива, чтобы найти наивысший индекс в разреженном массиве, который меньше запрошенного индекса, а затем использовать его для поиска фактического байта, который представляет начало желаемого символа.

Если вам нужно сохранить память, вам может потребоваться использовать библиотеку сжатия данных. Slurp в строках Unicode как полный Unicode, затем сжимайте их; затем, чтобы индексировать строку, сначала вы разжимаете эту строку. Это действительно спасет память, и будет легко и быстро получить код правильно, чтобы он работал; но это может привести к слишком большим нагрузкам на процессор, чтобы быть разумным.

  • 0
    OTOH это может быть полезно для строки с большим количеством английских метаданных ASCII, таких как, например, XML.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню