Комментарии 27
В статье не упомянута поддержка стримерами в разные аналитические базы типа вертики и кликхауса. Для многих — это решающий момент в выборе кодека.
Когда-то отдали предпочтение именно Avro при записи в service>kafka>dbms, ввиду хорошей интеграции.
Для RPC безусловно protobuf снимает головную боль при добавлении полей.
Более того, если часть полей тебе не нужна, то можно исключить их из схемы в одном из сервисов, тем самым снизив количество аллокаций.
Для RPC Avro добавит ещё дополнительную точку отказа — schema registry, да, он кластеризуется, даёт удобство, но тем не менее усложняет систему.
в протобафе это значение задано жестко, в зависимости от типа (0, пустая строка, false)
Это справедливо только для proto3
, proto2
вполне себе поддерживает параметр [default]
Насколько я понял статью, речь всё-таки о том, чтобы отличать вариант когда поле не передали вообще от варианта, когда поле передали с пустым (нулевым) значением. В протобаф в этой ситуации обычно используют well-known-types, которые по сути просто message оборачивающий одно поле стандартного типа. Так что корректнее, возможно, было бы написать в статье, что в протобаф это делается либо через one-of, либо через оборачивание поля в message.
Спасибо, добавил в статью. Еще есть эксперементальная поддежка ключевого слова optional. Переход из эксперементального состояния в стабильное ожидается в ближайших релизах. https://stackoverflow.com/questions/42622015/how-to-define-an-optional-field-in-protobuf-3
В целом, можно сказать, что вы будете удовлетворены размером и скоростью обоих форматов.
Вот прям так уверенно… Есть другие мнения, например:
In spite of being fast per se, Avro serialization has quickly revealed performance issues in our business scenarios. We discovered that Avro serialization/deserialization routines consume much of CPU time, resulting in heavy loads and reduced throughput.
В общем-то, у нас получилось примерно так же. Avro условно "быстра" пока нагрузка держится в пределах 1000 ops. Т.е. для API — видимо, неплохо для многих случаев. Но если надо прочитать из базы сотню тысяч записей и по ним сделать отчет — Avro станет узким местом (речь про gopkg.in/linkedin/goavro).
Не стоит придавать значение конкретным числам, так как скорость сериализации/десериализации, как и размер получающихся двоичных данных, зависит от конкретной схемы данных и от реализации сериализатора. Отметим лишь, что авро и протобаф занимают лидирующие позиции в подобных тестах.
Тут результат очень зависит от того, что и как делать. Если читать несколько полей из сотни, то результат у нас такой получался:
Avro-8 98437 19311 ns/op 11257 B/op 149 allocs/op
Flat-8 60032416 19.8 ns/op 0 B/op 0 allocs/op
Json-8 15333 83824 ns/op 11073 B/op 603 allocs/op
Т.е. Avro по чтению в четыре раза быстрее JSON и в 1000 раз медленнеее, чем FlatBuffers. Но это самый выгодный для FlatBuffer вариант, в других случаях по чтению он быстрее "всего" раз в 50.
В статье пишут о неэффективности чтения объединений, я видел в исходниках для дотнета код O(n), сразу зачесались руки подпачить с использованием словаря.
Avro тоже кодирует целые числа с помощью zigzag encoding делая их переменной длины. Кажется, протобуф использует тот же алгоритм
Стоит упомянуть о Bond от Microsoft.
Так же нет ни слова об экосистеме, в частности о расширяемости protoc компилятора. Не очень понятно зачем хранить где-то схему в случае с protobuf
Стоит ещё упомянуть SBE(simple binary encoding) по факту размер сообщения получается меньше чем в протобафе, плюс есть версионированик полей/сообщения/схемы.
SBE — это про скорость и пропускную способность, а не про размер и удобство. SBE один из самых быстрых из существующих сериализаторов/десириализаторов с пропускной способностью близкий к пропускной способности шины памяти. Основной сценарий его использования — реалтайм котировки, а не API общего назначения.
Я бы отметил кодек Cap'n Proto от автора Protobuf. Он достаточно быстрый, без лишних копирований, с гибкой схемой версионирования.
Странно что не сказанно о поодержке в AVRO логических типов (в терминологии AVRO) — UUID, Decimal etc.
Оба формата поддерживают механизмы расширения системы типов (logical types в авро и well known types в протобафе). Таким образом обе схемы дополнительно поддерживают сериализацию даты и времени (timestamp) и продолжительности времени (duration).
В отличии от авро, протобаф не поддерживает decimal и UUID.
1. Если в проекте уже есть хотя бы в одном месте протобаф или авро или что-то ещё — то оно будет использовано и в остальных местах.
2. Если ни в одном месте ещё нет ничего, то будет использовано то, с чем есть больше опыта у команды или тимлида.
3. Если ещё ничего не использовано и опыта нет ни с чем, то использовано будет что-попало и оно даже будет работать, ну потому что а почему бы и нет. Систем, где производительность упрётся в скорость бинарной сериализации — кот наплакал и вряд ли это вот прямо ваш продукт (в случае, если бинарной сериализации у у вас ещё нет и команда с ней не знакома).
В авро можно указать любое, допустимое значение, в протобафе это значение задано жестко, в зависимости от типа (0, пустая строка, false).
В protobuf 2 было указание дефолтного значения для необязательных полей. В реализации для C# (неофициальной, а той, что ближе к C#-style) прекрасно и в 3-й части можно указывать DefaultValue.
А что за альтернативная неофициальная реализация?
От Mark Gravell: https://github.com/protobuf-net/protobuf-net
Мой опыт с протобуфом на net core проекте:
- Быстрее BinaryFormatter (незначительно, выловили только в бенчмарках)
- Компактнее
- Нет сохранения ссылочной целостности (если есть циклы — не подходит)
- Удобный, строго типизированный API
- Обратная совместимость
Если в будущем придется иметь дело с сериализацией, мой личный выбор — протобуф
Protobuf vs Avro. Как сделать выбор?