Pull to refresh
249
0
Денис Ольшин @deNULL

Пользователь

Send message
Те варианты, что я видел, были заточены в первую очередь под английский язык (возможно, что-то упустил — смотрел довольно поверхностно). Впрочем, я даже о существовании SCSU не сразу узнал :)

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


В свою очередь, если делается продукт, который должен работать с текстами на произвольных языках (да пусть даже чтобы попросту нормальную пунктуацию вроде тире использовать), то куда лучше сразу обеспечить их поддержку, чем придумывать какие-то механизмы переключения кодировок.


Ей-богу, риторика в духе «8 бит хватит всем» мне кажется очень странной.

Думается, если есть такие опасения, то задачу сохранения целостности на протоколы передачи данных и стоит возложить. В любом случае, мне сложно представить ситуацию, когда с покусанной таким образом строкой клиент сможет сделать что-то осмысленное — независимо от того, по границе символа её обкусали или нет.


(Да и не для того это делалось же, чтобы эти строчки куда-то в сеть передавать)

Не соглашусь: поиск затруднён тем, что вхождение подстроки байт не гарантирует вхождение подстроки символов. Со сравнением строк это не связано.

Когда вы отмечали третий недостаток, вы цитировали моё сообщение:
И когда нужно что-то искать в массиве пожатых строк, это достаточно недорого делается вызовом функции декодирования для каждой.

Наверное, я неточно сформулировал ту фразу, но речь там шла не про подстроки, а именно про бинпоиск нужной строки (что требует таких же сравнений, как при сортировке).

Если так, тогда конкатенация строк требует перекодировки.
Да, это так. Все мутирующие операции тут требуют декодирования.

Строки в UTF-8 можно сортировать без декодирования, в этом и фишка.
Скажем так, это спорный момент.

Сортировать без декодирования так-то можно что угодно (и тем же бинпоиском искать потом). Сортировка прямо в UTF-8 гарантирует только то, что строки будут посортированы по порядковым кодам символов, а это неидеально: например, хорошо бы, чтобы сравнение шло без учёта регистра (чтобы буквы, отличающиеся только регистром, стояли рядом, а в Юникоде это почти никогда не так). Западноевропейские символы из Latin-1 Supplement и вовсе оторваны от родственных им аналогов без диакритики (как и русская «ё» от «е»). Так что если цель сортировать естественным образом, то декодировать нужно в любом случае, а потом применять Unicode collation algorithm.
Дополнил финальный раздел. Надеюсь, теперь точно недопониманий не возникнет :)
Есть вещи типа github.com/google/snappy
For instance, compared to the fastest mode of zlib, Snappy is an order of magnitude faster for most inputs, but the resulting compressed files are anywhere from 20% to 100% bigger.
Ну то есть тоже trade-off какой-то присутствует. Тоже было бы любопытно сравнить (я не утверждаю, что любое сжатие медленнее кодирования на нескольких ифах, но кажется, что второе заоптимизировать можно гораздо лучше, чем первое).

Просто базируясь на вашем названнии (UTF-C), я преполагаю что вы хотели бы предложить это в качестве стандарта в каком-то виде.
Ни в коем случае! Название это просто отсылка к UTF-8, на котором я построил свой подход (ну и мне показалась забавной созвучность USB-C, если честно :)

Напротив: я написал код (и статью) так, чтобы его можно было не только импортировать в свой проект по надобности, а скопировать и поменять под свои нужды. Я об этом говорю в разделе «Возможные доработки»: я считаю, что когда речь идёт о внутренних частях своего проекта, то иногда полезно не только стремиться к стандартизации (помним картинку про competing standards от xkcd), но и к кастомизации под конкретную задачу.
Прочитать статью, обращая внимание на каждый упомянутый недостаток? По правде сказать, мне казалось, предостережений я в тексте оставил порядочно :)
Вне BMP всё-таки только очень редко используемые иероглифы. Я, например, наугад открыл несколько статей в китайской Википедии, и не нашёл в них ни одного символа с кодом больше 0xFFFF.

Так же как, например, у кириллицы есть несколько дополнительных блоков кроме 0x0400 —0x04FF, но на практике мы с ними практически не сталкиваемся.
Зато в самом начале есть дисклеймер, где выделена ключевая мысль :)

Дисклеймер. Сразу сделаю несколько важных оговорок: описанное решение не предлагается как универсальная замена UTF-8, оно подходит только в узком списке случаев (о них ниже)
Я с вашего демо взял пример, у вас там сравнение 674 байт против 379 байт в вашей кодировке
Там всё-таки достаточно длинные примеры, просто для наглядности. На строках длиной менее ~100 символов gzip начинает давать текст даже длиннее, чем UTF-8 (и не забываем ещё про тот факт, что процесс сжатия всё-таки более затратный, чем кодирование — которое делается в один проход, с небольшим числом операций на каждый символ).

Но вы правы, возможно будет ещё интересно для понимания сделать, например, графики, где будет видно, на каких объемах какой подход работает лучше.

ASCII transparency это основное преимущество, если его нету то пусть будет просто компрессия, она сможет на типичных данных в разы преимущество давать.
Да, в каких-то областях применений это разумеется так. Но, например, когда речь про то, чтобы держать массив строк в памяти своего приложения ASCII transparency не требуется (хорошая компрессия требуется, но, повторюсь, надо смотреть на типичную длину строк).
Извините, но кажется отмеченный вами четвёртый недостаток полностью совпадает с третьим :)

Отмечу, что поскольку одна и та же строка кодируется одним и тем же способом, точное сравнение вполне допустимо делать побайтово, без декодирования. А для сравнения при сортировки сложность декодирования сравнима со сложностью декодирования UTF-8 (принципы у них одинаковые).

Честно говоря, у меня складывается ощущение, что вы хотите просто сказать, что я сделал плохую и бесполезную (по вашему мнению) вещь. Для меня это несколько неприятно, но я готов принять и такое мнение.
Да, уложит, но Хаффман не может «из воздуха» получить информацию о том, какой символ кодировать коротким кодом, а какой — подлиннее. Либо мы на каждую строчку дополнительно держим частоты символов (т.е. добавляем оверхед), либо строим какой-то отдельный глобальный словарь (но если мы хотим чтобы любая строка всегда кодировалась одним и тем же образом, он должен быть заранее зафиксирован). Такой «зашитый» в алгоритм частотный словарь — да, тоже приемлемая альтернатива, но мне показалась излишне сложной (и не факт, что стоящей того на практике).
Но обмен Вы отдали даже шанс на понимание Вашей кодировки чем-то, что с ней не знакомо и работает только с привычными стандартами.

Как я уже писал, речь про использование этой кодировки в своём коде. Всё взаимодействие с ней обёрнуто в функции Encode/Decode, которые на выходе/входе дают массив байт. Если нужно что-то с содержимым сделать — декодируем (обычно это нужно только в момент ввода или вывода), а если передать чему-то стороннему (или сбросить на диск, например) — передаём просто как байты.

При этом если Вам надо держать в памяти миллион коротких строк по 10 символов — почему бы не заменить это на 10 тысяч строк по 1000 символов, по принципу зип архива — если уж на то пошло?
Но «держать миллион строк по 10 символов» это же вводная, как её можно поменять на другую? :) Вот представьте, у нас смешанный словарь, содержащий слова разных языков мира. Или, например, список заголовков статей всех Википедий. Как вы их склеите так, чтобы иметь доступ за O(1) к каждому заголовку по его индексу?
Я не совсем понимаю, какой вывод из этого нужно сделать.

Обо всех этих недостатках я упомянул в теле статьи, о преимуществах тоже. Их существенность зависит от контекста: очевидно, что в одних классах задач встают одни требования, в других — другие. Поэтому в одном случае эффективнее одно решение, а в другом — другое.

Отдельно замечу, что во многих ситуациях UTF-8 точно так же требует кодирования/декодирования, как и мой подход. Но в отличие от, например, алгоритмов сжатия (у которых тоже своя область применимости) тут довольно простая логика, это не так затратно.
Но ведь по сути это и будет тем, что описано в статье. Грубо говоря, первый байт определяет кодировку и дальше тратится по одному байту на символ. Исключения, соответственно, кодируются 2-3 байтами (вместо 7 байт на html entities).
Если их немного, то как вариант можно хранить пометку «исключение» с хранением исходного текста в дополнительной таблице, при этом в основной хранить приведенный текст.
Мне кажется, мы с вами всё-таки немного про разные категории задач говорим. Вы больше про конкретный продукт, который кладёт тексты в какую-то базу, а я писал движок, который сам по себе «база данных» в некотором смысле, и у него нет знаний об используемом языке. И когда нужно что-то искать в массиве пожатых строк, это достаточно недорого делается вызовом функции декодирования для каждой.
Описанный вами подход выглядит очень похоже на описанный в статье, только вместо целого байта 0xFF в качестве маркера я трачу 1-3 бита. Да, чуть проще — чуть менее эффективно.

Так что поздравляю вас с изобретением велосипеда )
Спасибо, я старался!
Ну тогда попробуйте провести сравнение ваших результатов с результатами полученными алгоритмами сжатия, для более-менее длинных текстов. Можно даже и для коротких, если мы предположим что у нас есть универсальные словари комперссии для специфичных языков.

Но зачем? Основная область применения UTF-C — именно короткие тексты, когда алгоритмы сжатия не работают.
В моей статье есть целый раздел, озаглавленный словами «Зачем же выдумывать что-то новое?». Мне несколько обидно, что вы не уделили ему внимания.

Смысл разработки в экономии места в случаях, когда алгоритмы сжатия общего назначения неэффективны. Например, если вам нужно держать миллион коротких (10-20 символов) строк в памяти. В таких случаях алгоритмы вроде deflate дадут больше оверхеда, чем пользы.

Видимо, под «обычным текстом» подразумевается текст преимущественно на каком-то одном языке, чтобы под него можно было выбрать удобную однобайтовую кодировку?)


Мне вот хотелось уметь хорошо хранить строчки, язык которых заранее неизвестен.


Кстати, Википедия говорит, что вот SQL Server 2008 R2 как раз SCSU внутри себя использует, чтобы компактно строчки хранить.

Information

Rating
Does not participate
Location
Саратов, Саратовская обл., Россия
Registered
Activity