798bf160-5eda-4aa2-a741-bbfc48ac9f8f
Что это? 36 букв? Дефисики? Чтобы что? По телефону диктовать удобно было? Отдельно меня убивает группировка: 8-4-4-4-12. Кто это придумывал?
(на википедии пишут, что раньше вообще было
34dc23469000.0d.00.00.7c.5f.00.00.00 и urn:oid:2.25.113059749145936325402354257176981405696, так что мы еще легко отделались)Смотрел я на это, смотрел, и решил, что надо сжимать.
Первая мысль — base64. Это кодировка основана на простой идее: кодировать бинарные данные максимально «безопасными» символами, которые пролезут везде.
Что такое безопасные символы, спросит читатель? Так вышло, что из 256 символов стандартного ASCII половина (128) может попердолить если ошибиться с кодировкой, парочка трансформируется непредсказуемо, если открывать файл в текстовом режиме на разных системах, и еще 32 творят всякую дичь и скорее всего никак не отображаются на экране, что оставляет нам примерно 94 символа, которые отобразятся более-менее одинаково всегда.
Из этих 94 часть требует эскейпинга, если писать их в тексте программы, часть зарезервирована всякими системами (файловой, URL и так далее), короче, полагаться, чтобы совсем уж безопасно, можно только на буквы и цифры.
Теперь следите за руками. В английском 26 маленьких букв. Еще столько же больших. Итого 52. Добавляем 10 цифр, получается 62. ПОЧТИ дотянули до круглого 64.
А дальше начинается разброд. Поскольку идея такая простая, возникло буквально миллион версий base64, которые отличаются только тем, какие последние два символа выбраны.
Если зайти на википедию, можно увидеть, что большинство стандартов, которые прям стандарты-стандарты, берут
+ и /. Плюс еще куда ни шло, но вот / нам решительно не подходит – он явно будет плохо парситься внутри урлов и файловых путей, а пихать uuid в урлы и файловые пути — это святое.Я долго над этим медитировал и пришел к выводу, что, наверное, самый безопасный символ из оставшихся — это нижнее подчеркивание
_. Оно точно везде допускается, включая идентификаторы в программах. Но это только один. Какой второй?Вот, если что, полный спискок:
! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ ` { | } ~
Если бы я делал, я бы наверное выбрал
- — во-первых, потому что он уже в UUID используется, то есть мы ничего не теряем, а во-вторых он прикольно поддерживает тему заглавных/строчных в паре с _.Но так ли уж нам нужно именно 64 буквы? Есть более радикальная идея: а что если взять всего 62?
На самом деле, если использовать 64, то нам понадобится
⌈128 / log₂64⌉ = 22`символа. А если брать 62, то `⌈128 / log₂62⌉ = 22 все равно!Да, математика не такая красивая, по 6 бит удобнее откусывать, чем делить на 62 с остатком. Но! Мне кажется, если вы парсите UUID любым способом, кроме прямого memcpy 16 байт, вы уже проиграли игру в оптимизацию, и 22 лишних деления вам погоду не сделают. Зато универсальность!
В итоге UUID будут выглядеть как-то так:
ibIP7XtbjSUXesMuVW63JA
Сравните с тем, что было:
798bf160-5eda-4aa2-a741-bbfc48ac9f8f
Ну кайф же! А трафика, трафика сколько сэкономится! Единственная проблема, впрочем, что они потеряли свой легко узнаваемый вид.
Если играть совсем жестко, то можно все 94 доступных символа заиспользовать. Но тогда идентификатор сократится всего на 2 символа, а выглядеть они станут так:
;n'^}VR!5VIxlUl$\Q37
ИМХО, не стоит того.
А вот что можно провернуть, так это эмоджи! Вроде, если взять все односимвольные эмоджи без модификаторов, можно наскрести 1361 штук. Этого хватит на то, чтобы сократить 128-битные uuid до 13 символов. Можно даже только 1024 использовать, все равно 13 будет, плюс математика попроще.
Выглядеть будет так:
🩸💞🆑🪕🏪🤒🌡🥔🦐🪪🍑🕧🧋
С узнаваемостью проблем нет, а вот с эффективностью... Каждый эмоджи занимает 4 байта в UTF-8, т.е. мы получаем 13 * 4 = 52 байта, что больше даже 36-ти у текущего UUID.
Зато как красиво!