Как я упаковал JSON на 80% и написал свой бинарный формат

Packing Binary Is Fun

Автор вдохновился спором в Twitter о том, что «настоящие» разработчики не используют JSON, и решил создать собственный бинарный формат jBin. В статье подробно разбирается, как работает бинарная упаковка: от простого преобразования ASCII до varint, схем и упаковки типа поля в один байт. В итоге ему удалось сократить JSON-полезную нагрузку на 80% и попутно изобрести целый язык описания схем.

«Насколько сложно сделать собственный бинарный формат?» — Наверное, это просто небольшая запись в режиме wb. К сожалению, это была не просто запись в режиме wb.
  1. trashb

    Мне не хватает нескольких важных частей, которые, я бы сказал, нужны любому (бинарному) формату.

    - магический заголовок

    - номер версии

    - crc или проверка на повреждение данных

    Кроме того, я бы сказал, что в этом случае лучше написать собственный текстовый парсер, а не парсить бинарный формат; это похоже на спор о unixlike config против windows regedit. Я предпочёл бы что-то другое, а не json, но всё ещё читаемое как txt.

    Даже приведённый внизу пример json можно сжать с 418 символов до 166, заменив имена полей на одиночные символы и убрав пробелы. Почти вся экономия в этом формате достигается за счёт отсутствия имён полей и позиционно-зависимой раскладки. Можно выбрать разделители или организовать так, чтобы байт указывал тип (+размер), например, следующая строка кодирует пример данных почти (85 байт против 80 байт) так же эффективно, но при этом остаётся читаемой и поддерживает интерпретацию utf-8.

    123456789;LeroyJenkins;60;alliance;p,100,200,300;i,999,1,1;i,45,100,0;a,s,120;a,a,45;

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

    { "itemId": 999, "quantity": 1, "isSoulbound": false }

    i,999,1,0

    могло бы стать:

    default = { "itemId": 0, "quantity": 1, "isSoulbound": false }

    { "itemId": 999}

    i,999

  2. ErikHuisman

    Я тоже хочу быть настоящим разработчиком, так что я просто GZIP-ую JSON, чтобы сделать его бинарным.

  3. Skwid

    Одним из моих любимых приключений по стрижке яка на прошлой работе было написание парсера in place UBJSON-декодера для ~1 МБ данных на устройстве с примерно таким же объёмом свободной памяти. Быстрый (достаточно) доступ по ключу, бинарный поиск с несколькими сокращениями для преимущественно числовой полезной нагрузки.

    Он строил индекс размером, может, 30 байт, чтобы ускорить процесс, но также чтобы продолжать работать с хвостом старого сообщения, пока новое перезаписывает его начало.

    Должен ли был дизайн системы требовать всего этого от устройства с 4 МБ памяти? Вероятно, нет. Но это работало, и я отлично провёл время

Ещё за этот день

2026-09-28