gammaker
> Если поменялись параметры, но эти различия можно выразить через старые
> параметры, то это реализуется через вычисляемые свойства.
Таких изменений будет примерно 0%. Если разработчики заранее знали какие свойства можно бы добавить, они с тем же успехом могли их добавить сразу. Ну т.е. в случае Image - если ты заранее знаешь что изображения бывают неквадратными, то кто мешает вместо вычисляемых полей сразу передавать два измерения. 4 байта экономии на картинку? Тогда ты вряд ли добавишь эти поля в будущем.
А расширять формат ты будешь когда выяснится что с картинкой надо передавать DPI, или скажем отсылать ее в CMYK, в общем делать то что не предусмотрел в первой версии.
kipar
> Таких изменений будет примерно 0%.
Думаю, что всё же побольше. Например, я использую вычисляемые свойства, чтобы задать значение в некотором диапазоне. Допустим, у нас некоторый параметр изменяется в интервале 3456 - 3678. Любое число из этого интервала можно представить в виде int16, а можно сделать поле типа uint8 и свойство, которое прибавляет 3456 к этому полю. И если мы храним миллион таких структур, то мы уже экономим мегабайт. Свойства позволяют прозрачно для программы переходить от первого варианта ко второму и наоборот. Физическая структура данных меняется, а логически она та же самая.
>Если разработчики заранее знали какие
> свойства можно бы добавить, они с тем же успехом могли их добавить сразу.
Зачем тратить байты на то, что может не понадобиться?
kipar
> 4 байта экономии на картинку?
Это я конечно дурацкий пример привёл, первое что пришло в голову. Но можно найти другие применения, когда экономия пары байт в структуре даст огромную выгоду, например в ситуации, которую я описал в начале этого поста.
kipar
> А расширять формат ты будешь когда выяснится что с картинкой надо передавать DPI
Просто добавить поле DPI и это все изменения. А при чтении старых файлов использовать значение по умолчанию. С этим бы даже protobuf бы справился.
kipar
> или скажем отсылать ее в CMYK
Это просто изменит физический тип поля Data, не изменяя логического. При сериализации / десериализации оно будет корректно переконвертировано в нужный формат.
Дич какая-то дикая. Либо быстро и платформозависимо. Либо медленно, строчками ASCII и float/double/int.
lookid
> Дич какая-то дикая. Либо быстро и платформозависимо. Либо медленно, строчками
> ASCII и float/double/int.
Можно и средне через бинарное представление форматов типа json/xml, etc.
Ускоряется паркинг, уменьшается объем памяти, но конечно блокнотом не поредактировать
Кстaти, а я ведь намедни предлагал:
http://gamedev.ru/flame/forum/?id=238115
А чем этот формат лучше, чем ASN.1 ?
lookid
> Дич какая-то дикая. Либо быстро и платформозависимо. Либо медленно, строчками
> ASCII и float/double/int.
С чего ты так решил? Байты - они везде байты, на разных архитектурах может отличаться только порядок Little Endian и Big Endian. IEEE 754 тоже в наше время поддерживается везде. Если файл содержит информацию о том, в каком порядке байт хранятся данные, то парсер может проверить это. В случае совпадения он может замапить напрямую данные на структуры и массивы в программе без десериализации. В случае несовпадения - сконвертировать при первом чтении, записать сконвертированный файл куда-нибудь в кеш, а дальше доставать из кеша файл нативного формата.
KILLJOY
> А чем этот формат лучше, чем ASN.1 ?
ASN.1 решает только проблему платформозависимости бинарных данных. При этом он не описывает физическую структуру файла, а только логическую. И логическую структуру он описывает гораздо хуже, чем мой формат - только на низком уровне - число, строка, массив и ограничения на их интервалы.
Например мой формат позволяет контролировать каждый бит каждого поля. Например можно сделать даже компактно упакованный массив 19-битных интов. Можно описать структуру BMP, PNG или любого другого из существующих форматов или даже самого себя - по крайней мере, я над этим работаю и уже близок к этой цели. А в ASN.1, protobuf и прочих подобных есть только некоторое подмножество фич для создания новых кастомных форматов без особого контроля над тем, как там всё кодируется. Описать себя они только не в состоянии.
Сейчас вот готовлю пример спецификации PNG, написанной на моём языке. Когда она будет готова, можно будет сравнить размер моего кода и текста самой спецификации, написанной на человеческом языке, непонятном компьютеру. Вот только сейчас произошёл кое-какой затык. Я нашёл в спецификации фичу, по идее бессмысленную и вряд ли используемую на практике в реальных PNG-файлах, но она не вписывается в мою систему типов, и я сейчас пытаюсь придумать, как её расширить без костылей и усложнений.
Давай сразу JPG
KILLJOY
> Давай сразу JPG
У меня уже PNG в процессе, а с JPG я мало знаком. Может как-нибудь потом.
Смахивает на очередное рукоблудие.
Всё описанное достигается с помощью protobuf. Хотя сами проблемы описаны как-то мутно. Проблема Big/Little Endian сегодня возникает примерно никогда. То, что формат хранения данных на диске должен определять способ хранения этих данных в памяти процесса это лютейший бред. Одни и те же данные можно распихать по оперативке как угодно не меняя при этом формата хранения или наоборот записать по другому. Те же базы данных и ORM в пример. Если уж даже в protobuf остались какие-то проблемы, то в любой другой альтернативе их будет ещё больше. И зачем, в таком случае кому-то может понадобиться поделка неизвестного анонима даже если предположить, что там не будет багов и ей не нужна будет поддержка (что, естественно, невыполнимо)?
Пример решения подобной задачи "по месту" и "на коленке" (боян): https://gcup.ru/forum/62-45089-2#698967
Zefick
> То, что формат хранения данных на диске должен определять способ хранения этих
> данных в памяти процесса это лютейший бред.
Это ещё почему? Скорость же. Прочитал одним куском без парсинга и можно работать. Или можно даже в память замапить, не читая с диска всё.
Protobuf тормозной и так не может. А у Flatbuffers свои ограничения.
Особенно в игровых движках актуально, поэтому все делают свои форматы, когда можно сразу считать и запихнуть в видеокарту. И моя разработка в этом очень поможет, потому что позволяет ясным языком указать, какой формат мы хотим, вместо того, чтобы вручную писать код записи и чтения формата.
Zefick
> Одни и те же данные можно распихать по оперативке как угодно не меняя при этом
> формата хранения или наоборот записать по другому.
И то же самое я предлагаю для файлов. Одни и те же логически данные можно писать в файл по-разному. Потом программа говорит, как она хочет разложить их в оперативке. Если способ раскладки внутри файла и желаемый способ в оперативке совпадают, то файл считывается в оперативку быстро как есть. Если нет, то всё автоматически конвертируется - не надо писать никакого ручного кода.
Zefick
> И зачем, в таком случае кому-то может понадобиться поделка неизвестного анонима
Если так говорить, то можно просто запретить всем кроме гуглов что-то там разрабатывать.
Тому, что я делаю, аналогов в мире нет. Область применения этого в десятки раз шире всех форматов вместе взятых, потому что решает все проблемы: сложности описания, создания и поддержки (версионности) бинарных форматов, преобразований между форматами, компактности, эффективности. И даже, в перспективе, человекочитаемости - пусть файлы и бинарные, но будет единая утилита, которая сможет открыть абсолютно любой бинарный файл, созданный по моей технологии, показать его в человекочитаемом формате и даже отобразить картинки и воспроизвести звуки, которые в нём закодированы. И она даже сможет открыть обычный "неумный" файл, если рядом будет лежать описание его формата.
Zefick
> Проблема Big/Little Endian сегодня возникает примерно никогда.
Есть форматы и протоколы, где используется Big-Endian кодирование и его поддержка в моём формате пригодится для их поддержки.
Первое, что я предлагаю - это формальный язык описания структуры файла, который сможет понять компьютер и автоматически сгенерировать готовый к использованию парсер и экспортер. Вместо того, чтобы писать громоздкие спецификации форматов, где человеческим текстом и таблицами написано, как там байты разложены и как его парсить, я предлагаю писать на языке, который будет понятен не только человеку, но и компьютеру. Написал такую спецификацию своего формата и не надо ничего реализовывать - сразу же можно его применять в любом языке программирования, куда доберётся моя библиотека.
Скоро будет пример описания структуры формата PNG на моём языке. Я много искал, но не нашёл ни одного языка, который бы мог описать какой-нибудь существующий формат, например PNG или хотя бы даже TGA. Ближайшие аналоги - Protobuf и ASN.1 точно не могут, потому что у них для этого слишком примитивный язык описания схемы.
gammaker
> Protobuf тормозной и так не может.
Тем не менее ты предлагаешь то же самое и непонятно откуда там возьмётся скорость. Ты думаешь авторы protobuf об этом не думали?
И там, где нужна скорость, никто и не будет использовать какие-то непонятные либы, которые обещают сказочные ништяки непонятно с чего. Обычно либо мирятся с накладными расходами либо мирятся.
> А у Flatbuffers свои ограничения.
Скорее всего эти ограничения опять вытекают из её возможностей (в частности кроссплатформенность) и являются трейд-оффами.
> Тому, что я делаю, аналогов в мире нет.
Под конкретную задачу всегда найдётся свой аналог. Не всем нужна поддержка кучи языков (которую, я думаю, ты не осилишь) и они давно нашли нужное решение для своего. В Java, например, есть библиотека Kryo, которая решает многие проблемы встроенной сериализации, а также добавляет ей в скорости и уменьшает размер выходных файлов. То, что она самая популярная говорит о том, что больше никому не удалось сделать что-то лучше. Причём так как в Java есть рефлексия, то все эти пляски с бубном вокруг написания каких-то там файлов на непонятном языке автоматически становятся не нужны. На хрена кому-то может понадобится кроссплатформенное решение, не учитывающее особенности платформы явы и игнорирующее её преимущества, мне решительно непонятно.
А кому нужна поддержка нескольких языков те, скорее всего, пишут микросервисы, где скорость сериализации вообще почти ни на что не влияет. И тут как раз вкатывается protobuf. А если ты пытаешься угодить сразу всем, то не получится угодить никому.
Zefick
> Тем не менее ты предлагаешь то же самое и непонятно откуда там возьмётся скорость.
Я предлагаю совсем другое. Я предлагаю пользователю создать свой формат, максимально подходящий под его конкретную задачу, но при этом не писать его парсер и экспортер. В большинстве случаев эта задача будет простая и на моём языке пользователь должен написать всего полэкрана описания формата.
Zefick
> Скорее всего эти ограничения опять вытекают из её возможностей (в частности
> кроссплатформенность) и являются трейд-оффами.
А мой язык не содержит никаких трейд-оффов вообще. Пользователю предоставляется неограниченная свобода продумать свой формат до всех деталей, описывая его на моём языке, и самому решить, какие у него будут трейд-оффы. Если нужна компактность, а скорость не важна, он может экономить каждый бит и применять сжатие, если наоборот, то можно расположить данные, да ещё и с выравниванием так, чтобы это можно было сразу мапить в оперативку и работать. Или может даже создать оба варианта и прозрачно для программы переключаться между ними.
Zefick
> Под конкретную задачу всегда найдётся свой аналог.
Давай я тебе опишу задачу, с которой столкнулся на работе и ты подберёшь решение, которое я мог бы использовать для её решения. Лично я не нашёл ничего подходящего и пришлось пилить свой кастомный формат. Если бы моя технология была уже готова, я бы мог сделать это за 5 минут, а не за пару дней, при этом оно было бы гораздо более поддерживаемым и гибким в долгосрочной перспективе.
Итак, есть устройства, которые регистрируют значения некоторых параметров, которых около тысячи. Параметры приходят от внешнего устройства, на каждый параметр отводится от 1 до 19 бит и они либо дискретные (чаще всего false / true), либо это числа с фиксированной запятой в некотором интервале. Нужно все эти параметры записывать в файл и при наличии Интернет-соединения отправлять на сервер. Необходимо при этом минимизировать трафик, занимаемое на сервере пространство, а также нагрузку на сервер при приёме и раздаче этих данных клиентом. Поэтому, очевидно, пришлось параметры хранить плотно, выделяя им в файле ровно столько бит, сколько нужно для хранения этого параметра. Было решено также сжимать наборы значений для каждого параметра индивидуально, чтобы сервер мог выдирать из файла и сразу выдавать сжатые блоки клиентам, которые хотят построить график какого-то конкретного параметра - сразу все 1000 его не интересуют. Таким образом, клиент только принимает файл и кладёт его себе туда, где он сможет его найти по запросу от клиента.
Устройство-регистратор и сервер написаны на Go. Клиент будет написан на TypeScript и выполняться в браузере. Именно на него будет возложена работа по анализу данных. Клиент запрашивает нужные параметры за некоторый промежуток времени у сервера, получает набор сжатых блоков, их разжимает, распаковывает побитово запакованные параметры и рисует их график, либо выполняет какие-то другие задачи по анализу данных.
Технологию, привязанную к какому-то одному языку использовать нельзя, потому что используется два разных языка. А что бы мне дал Protobuf? Он не умеет битовую запаковку и не умеет сжатие. Пришлось бы это в любом случае делать руками и передавать туда просто тупой массив байт. А это как раз самая трудоёмкая часть, которую придётся ещё и на двух языках реализовывать.
Ещё нужно учитывать, что устройство-регистратор слабое - одно ARM-ядро с частотой 800 MHz и памятью 512 МБ, наверняка Protobuf дал бы ещё и оверхед огромный, и при этом не принёс бы практически никакой пользы.
На моём языке формат, который пришлось вручную реализовывать, описывается в 10 строчек, и можно использовать.
Zefick
> Причём так как в Java есть рефлексия, то все эти пляски с бубном вокруг
> написания каких-то там файлов на непонятном языке автоматически становятся не нужны.
Так с рефлексией писать их и не обязательно. Но на языке можно описать зависимости, свойства и другие логические элементы структуры, которые через рефлексию не получить. И язык этот вполне себе понятный, потому что ясно описывает структуру того, что мы хотим получить.
Zefick
> На хрена кому-то может понадобится кроссплатформенное решение, не учитывающее
> особенности платформы явы и игнорирующее её преимущества, мне решительно
> непонятно.
С чего ты решил, что не учитывающее? По мере развития можно учитывать все преимущества всех языков и платформ, ведь ограничений никаких не накладывается.
Zefick
> есть библиотека Kryo
хотя readUnknownTagData как бы намекает, что наверно перед каждым объектом/полем храниться его тип или что-то типа указателя на тип, что как бы раздувает бинарное представление. ещё есть надежда что "a simple schema is written" подразумевает не только имена полей, а ещё и типы полей.
Тема в архиве.