повысить сериализацию против буферов протокола Google?

Кто-нибудь, имеющий опыт работы с этими библиотеками, может прокомментировать, какую из них они предпочитают? Были ли различия в производительности или трудности в использовании?


person 0xC0DEFACE    schedule 30.06.2009    source источник
comment
Это близко к дубликату stackoverflow.com/questions/321619/c-serialization- производительность, так что это тоже может быть полезно   -  person Laserallan    schedule 07.09.2009


Ответы (11)


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

С boost :: serialization вы сначала пишете свои собственные структуры / классы, а затем добавляете методы архивирования, но у вас все еще остаются несколько довольно «тонких» классов, которые можно использовать в качестве членов данных, унаследованных и т. Д.

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

person Magnus Österlind    schedule 30.06.2009
comment
Очень часто вам не нужно переносить данные в ваши собственные внутренние структуры и из них - вы можете заполнить эти структуры напрямую с помощью буферов протокола. По сути, это классы значений, у них есть семантика перемещения, и они прекрасно работают с коллекциями STL и Boost. - person Tom Swirly; 07.05.2014

Я давно использую Boost Serialization и просто копался в буферах протоколов, и я думаю, что они не имеют той же цели. BS (не ожидал этого) сохраняет ваши объекты C ++ в поток, тогда как PB - это формат обмена, который вы читаете в / из.

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

Это означает, что с BS вы получаете больше данных по сети, но вам не нужно перестраивать всю структуру ваших объектов, тогда как буферы протокола более компактны, но после чтения архива необходимо выполнить больше работы. Как следует из названия, один предназначен для протоколов (не зависящий от языка, эффективная передача данных), другой - для сериализации (сохранение простых объектов).

Так что для вас важнее: скорость / эффективность использования пространства или чистый код?

person ndfred    schedule 28.03.2010

Есть несколько дополнительных проблем с boost.serialization, которые я добавлю к этому миксу. Предостережение: у меня нет прямого опыта работы с буферами протоколов, кроме беглого просмотра документов.

Обратите внимание: хотя я считаю, что boost и boost.serialization хороши в том, что они делают, я пришел к выводу, что форматы архивов по умолчанию, с которыми он поставляется, не лучший выбор для формата проводов.

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

Более новые версии boost.serialization могут не создавать архивы, которые можно десериализовать в более старых версиях. (обратное неверно: новые версии всегда предназначены для десериализации архивов, созданных более старыми версиями). Это привело к возникновению у нас следующих проблем:

  • И наше клиентское, и серверное программное обеспечение создают сериализованные объекты, которые потребляет другой, поэтому мы можем перейти к более новой boost.serialization, только если мы обновим и клиент, и сервер синхронно. (Это довольно сложная задача в среде, где у вас нет полного контроля над своими клиентами).
  • Boost поставляется в виде одной большой библиотеки с общими частями, и код сериализации и другие части библиотеки boost (например, shared_ptr) могут использоваться в одном файле, я не могу обновить любой части boost, потому что я не могу обновить boost.serialization. Я не уверен, возможно ли / безопасно / разумно попытаться связать несколько версий повышения в один исполняемый файл, или если у нас есть бюджет / энергия для рефакторинга битов, которые должны оставаться в более старой версии повышения, в отдельный исполняемый файл (в нашем случае это DLL).
  • Старая версия boost, на которой мы застряли, не поддерживает последнюю версию используемого нами компилятора, поэтому мы тоже застряли на старой версии компилятора.

Google, похоже, действительно публикует формат проводных буферов протоколов, и Википедия описывает их как прямую совместимость, обратную совместимость (хотя я думаю, что Википедия имеет в виду управление версиями данных, скорее чем управление версиями библиотеки буферов протокола). Хотя ни то, ни другое не является гарантией обратной совместимости, мне это кажется более сильным признаком.

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

Сноска: бесстыдная пробка для соответствующего ответа, сделанного мной.

person bacar    schedule 25.11.2011
comment
К вашему сведению: 2,5 года спустя у меня есть большой непосредственный опыт работы с буферами протоколов, и я поддерживаю свои замечания выше. - person bacar; 25.07.2014
comment
Что означает, что старая версия boost, на которой мы застряли, не поддерживает последнюю версию используемого нами компилятора? Использует ли Boost какие-то нестандартные языковые расширения или почему это произошло? - person Hi-Angel; 07.05.2018
comment
Хороший вопрос. Думаю, да - например, я полагаю, что boost.thread и boost.interprocess используют (или использовали) специфичные для платформы API для реализации функций, которые невозможно реализовать переносимо. Кроме того, соответствие стандартам компиляторов варьируется в зависимости от версии, поэтому что-то, что работало, например, MSVC 2005 может не работать / компилироваться с более поздними версиями. Документы Boost.org, какие компиляторы работают: boost.org/doc/libs/1_67_0/libs/log/doc/html/log/ - person bacar; 08.05.2018

Повышение сериализации

  • это библиотека для записи данных в поток.
  • не сжимает данные.
  • не поддерживает автоматическое управление версиями данных.
  • поддерживает контейнеры STL.
  • свойства записываемых данных зависят от выбранных потоков (например, порядок байтов, сжатие).

Буферы протокола

  • генерирует код из описания интерфейса (по умолчанию поддерживает C ++, Python и Java. C, C # и другие сторонние).
  • опционально сжимает данные.
  • автоматически обрабатывает версии данных.
  • обрабатывает порядковый номер обмена между платформами.
  • не поддерживает контейнеры STL.

Boost serialization - это библиотека для преобразования объекта в сериализованный поток данных. Буферы протокола делают то же самое, но также выполняют другую работу за вас (например, управление версиями и обратный порядок байтов). Повысить сериализацию проще для «небольших простых задач». Буферы протокола, вероятно, лучше подходят для «более крупной инфраструктуры».

РЕДАКТИРОВАТЬ: 24-11-10: Добавлено «автоматически» в управление версиями BS.

person Nick    schedule 07.06.2010
comment
Хм ... это кажется не совсем правильным, поскольку BS имеет управление версиями, и, насколько я знаю, проблемы с порядком байтов зависят от того, какой формат сериализации вы используете. - person Martin Ba; 24.11.2010
comment
Хорошо, это не поддерживает автоматически. Вы должны явно встроить управление версиями в свой код сериализации, сериализатор не сделает этого за вас. - person Nick; 24.11.2010
comment
Повышенная сериализация включала управление версиями данных с самого начала. Это по умолчанию и автоматически. Если вы не хотите, чтобы какой-либо тип данных был версионным, вы можете отключить его для каждого типа. Но обычно этого почти никогда не делается. - person Robert Ramey; 08.02.2014
comment
Сжатие данных обычно выполняется композицией с помощью boost iostream. Это не часть ускоренной сериализации, потому что это было бы излишним. - person Robert Ramey; 08.02.2014
comment
Сжатие данных с ускорением очень легко добавить к этому миксу: stackoverflow.com/questions/1753469/ - person Avio; 14.11.2014

У меня нет опыта ускоренной сериализации, но я использовал буферы протокола. Мне очень нравятся буферы протоколов. Имейте в виду следующее (я говорю это, не зная о повышении).

  • Буферы протокола очень эффективны, поэтому я не полагаю, что это серьезная проблема по сравнению с ускорением.
  • Буферы протокола обеспечивают промежуточное представление, которое работает с другими языками (Python и Java ... и другие в разработке). Если вы знаете, что используете только C ++, возможно, Boost лучше, но возможность использовать другие языки - это хорошо.
  • Буферы протокола больше похожи на контейнеры данных ... здесь нет объектно-ориентированного характера, такого как наследование. Подумайте о структуре того, что вы хотите сериализовать.
  • Буферы протокола гибки, потому что вы можете добавлять «необязательные» поля. Это в основном означает, что вы можете изменить структуру буфера протокола без нарушения совместимости.

Надеюсь это поможет.

person Tom    schedule 30.06.2009

boost.serialization просто требует компилятора C ++ и дает вам синтаксический сахар, например

serialize_obj >> archive;
// ...
unserialize_obj << archive;

для сохранения и загрузки. Если C ++ - единственный язык, который вы используете, вам следует серьезно подойти к boost.serialization.

Я быстро взглянул на буферы протокола Google. Из того, что я вижу, я бы сказал, что это напрямую не сопоставимо с boost.serialization. Вы должны добавить компилятор для файлов .proto в свою инструментальную цепочку и поддерживать сами файлы .proto. API не интегрируется в C ++, как это делает boost.serialization.

boost.serialization отлично справляется со своей задачей: сериализовать объекты C ++ :) OTOH API-интерфейс запросов, такой как буферы протокола Google, дает вам большую гибкость.

Поскольку я пока использовал только boost.serialization, я не могу комментировать сравнение производительности.

person Maik Beckmann    schedule 30.06.2009

Исправление к приведенному выше (думаю, это ответ) о Boost Сериализация:

Он ДЕЙСТВИТЕЛЬНО позволяет поддерживать управление версиями данных .

Если нужно сжатие - используйте сжатый поток.

Может обрабатывать обратный обмен между платформами, поскольку кодировка может быть текстовой, двоичной или XML.

person Robert Ramey    schedule 07.06.2010

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

Единственная трудность, с которой я столкнулся с protobufs, заключалась в том, что они назвали очень часто используемую функцию в своем сгенерированном коде GetMessage (), что, конечно, конфликтует с макросом Win32 GetMessage.

Я все еще очень рекомендую protobufs. Они очень полезны.

person i_am_jorf    schedule 30.06.2009
comment
Я ставлю +1, когда мой лимит будет восстановлен. Спасибо, что упомянули GetMessage препятствие. Что-то думать о... - person Anthony; 13.07.2012

Я знаю, что сейчас это более старый вопрос, но я подумал, что брошу свои 2 пенса!

С Boost вы получаете возможность написать некоторую проверку данных в ваших классах; это хорошо, потому что определение данных и проверки на достоверность находятся в одном месте.

Лучшее, что вы можете сделать с GPB, - это помещать комментарии в файл .proto и надеяться, вопреки всякой надежде, что тот, кто его использует, прочитает его, обратит на это внимание и сам выполнит проверки достоверности.

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

Таким образом, я считаю, что GPB не подходит для разработок, где мало возможностей регулярно встречаться и разговаривать со всеми членами команды.

== РЕДАКТИРОВАТЬ ==

Я имею в виду следующее:

message Foo
{
    int32 bearing = 1;
}

Кто теперь должен сказать, каков допустимый диапазон bearing? Мы можем иметь

message Foo
{
    int32 bearing = 1;  // Valid between 0 and 359
}

Но это зависит от того, кто это прочитает и напишет для него код. Например, если вы его отредактируете, и ограничение станет:

message Foo
{
    int32 bearing = 1;  // Valid between -180 and +180
}

вы полностью зависите от всех, кто использовал этот .proto, обновляя свой код. Это ненадежно и дорого.

По крайней мере, с сериализацией Boost вы распространяете один класс C ++, и в него могут быть встроены проверки достоверности данных. Если эти ограничения изменятся, то больше никому не нужно будет выполнять какую-либо работу, кроме как убедиться, что они используют ту же версию исходного кода, что и вы.

Альтернатива

Есть альтернатива: ASN.1. Это древний вариант, но в нем есть действительно очень полезные вещи:

Foo ::= SEQUENCE
{
   bearing INTEGER (0..359)
}

Обратите внимание на ограничение. Поэтому всякий раз, когда кто-либо использует этот файл .asn, генерирует код, он получает код, который автоматически проверяет, находится ли bearing где-то между 0 и 359. Если вы обновите файл .asn,

Foo ::= SEQUENCE
{
   bearing INTEGER (-180..180)
}

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

Вы также можете:

bearingMin INTEGER ::= 0
bearingMax INTEGER ::= 360

Foo ::= SEQUENCE
{
   bearing INTEGER (bearingMin..<bearingMax)
}

Обратите внимание на <. А также в большинстве инструментов BearMin и BearMax могут появляться как константы в сгенерированном коде. Это очень полезно.

Ограничения могут быть довольно сложными:

Garr ::= INTEGER (0..10 | 25..32)

См. Главу 13 в этом PDF; это потрясающе, что ты умеешь;

Массивы тоже могут быть ограничены:

Bar ::= SEQUENCE (SIZE(1..5)) OF Foo
Sna ::= SEQUENCE (SIZE(5)) OF Foo
Fee ::= SEQUENCE 
{
    boo SEQUENCE (SIZE(1..<6)) OF INTEGER (-180<..<180)
}

ASN.1 старомоден, но все еще активно развивается, широко используется (ваш мобильный телефон часто использует его) и гораздо более гибок, чем большинство других технологий сериализации. Единственный недостаток, который я вижу, это отсутствие достойного генератора кода для Python. Если вы используете C / C ++, C #, Java, ADA, тогда вам хорошо подойдет сочетание бесплатных (C / C ++, ADA) и коммерческих (C / C ++, C #, JAVA) инструментов.

Мне особенно нравится широкий выбор бинарных и текстовых форматов проводов. Это делает его чрезвычайно удобным в некоторых проектах. Список форматов проводов в настоящее время включает:

  • BER (двоичный)
  • PER (двоичный, выровненный и невыровненный. Это очень эффективно. Например, INTEGER, ограниченный между 0 и 15, будет занимать только 4 bits на проводе)
  • ООР
  • DER (другой двоичный файл)
  • XML (также XER)
  • JSON (совершенно новый, поддержка инструментов все еще развивается)

плюс другие.

Обратите внимание на два последних? Да, вы можете определять структуры данных в ASN.1, генерировать код и отправлять / получать сообщения в XML и JSON. Неплохо для технологии, зародившейся еще в 1980-х годах.

Управление версиями осуществляется иначе, чем в GPB. Вы можете разрешить расширения:

Foo ::= SEQUENCE
{
   bearing INTEGER (-180..180),
   ...
}

Это означает, что позже я смогу добавить Foo, и более старые системы, в которых есть эта версия, все еще могут работать (но могут получить доступ только к полю bearing).

Я очень высоко оцениваю ASN.1. Это может быть проблемой (инструменты могут стоить денег, сгенерированный код не обязательно красив и т. Д.). Но ограничения - это поистине фантастическая особенность, которая снова и снова спасает меня от целой тонны сердечной боли. Заставляет разработчиков сильно сетовать, когда кодеры / декодеры сообщают, что они сгенерировали пустые данные.

Другие ссылки:

Наблюдения

Чтобы поделиться данными:

  • Подходы с использованием первого кода (например, ускоренная сериализация) ограничивают вас исходным языком (например, C ++) или вынуждают вас выполнять много дополнительной работы на другом языке
  • Schema first is better, but
    • A lot of these leave big gaps in the sharing contract (i.e. no constraints). GPB is annoying in this regard, because it is otherwise very good.
    • Некоторые из них имеют ограничения (например, XSD, JSON), но страдают отрывочной поддержкой инструментов.
    • Например, Microsoft xsd.exe активно игнорирует ограничения в файлах xsd (оправдание MS действительно слабое). XSD хорош (с точки зрения ограничений), но если вы не можете доверять другому парню, что он использует хороший инструмент XSD, который применяет их для него / нее, тогда ценность XSD уменьшается.
    • Валидаторы JSON - это нормально, но они не делают ничего, чтобы помочь вам сформировать JSON, и не вызываются автоматически. Нет никакой гарантии, что кто-то, отправивший вам сообщение JSON, пропустил его через валидатор. Вы должны не забыть проверить это самостоятельно.
    • Все инструменты ASN.1, похоже, реализуют проверку ограничений.

Так что для меня это делает ASN.1. Это тот, который с наименьшей вероятностью приведет к тому, что кто-то совершит ошибку, потому что он имеет правильные функции и где все инструменты, по-видимому, стремятся полностью реализовать эти функции, и он достаточно нейтрален в отношении языка для большинства целей.

Честно говоря, если бы GPB добавило механизм ограничений, это было бы победителем. XSD близок, но инструменты почти всегда бесполезны. Если бы были приличные генераторы кода на других языках, схема JSON была бы неплохой.

Если бы в GPB были добавлены ограничения (примечание: это не изменит ни один из форматов проводов), я бы рекомендовал его всем практически для любых целей. Хотя uPER ASN.1 очень полезен для радиосвязи.

person bazza    schedule 14.01.2018

Как и почти все в инженерном деле, я отвечу ... «в зависимости от обстоятельств».

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

Для меня это действительно сводится к рабочему процессу и тому, нужно ли вам что-то другое, кроме C ++, на другом конце.

Если вы хотите сначала выяснить содержимое сообщения и строите систему с нуля, используйте буферы протоколов. Вы можете думать о сообщении абстрактно, а затем автоматически сгенерировать код на любом языке, который вы хотите (сторонние плагины доступны практически для всего). Кроме того, я считаю, что сотрудничество упрощается с помощью буферов протоколов. Я просто отправляю файл .proto, и тогда другая команда имеет четкое представление о том, какие данные передаются. Я им тоже ничего не навязываю. Если они хотят использовать Java - вперед!

Если я уже создал класс на C ++ (и это происходило чаще, чем нет), и я хочу отправить эти данные по сети сейчас, Boost Serialization, очевидно, имеет большое значение (особенно там, где у меня уже есть зависимость Boost где-то еще ).

person It'sPete    schedule 22.05.2015

Вы можете использовать ускоренную сериализацию в тесной связи с вашими «реальными» объектами домена и сериализовать полную иерархию объектов (наследование). Protobuf не поддерживает наследование, поэтому вам придется использовать агрегацию. Люди утверждают, что Protobuf следует использовать для DTO (объектов передачи данных), а не для самих объектов основной области. Я использовал как boost :: serialization, так и protobuf. Следует учитывать производительность boost :: serialization, альтернативой может быть cereal.

person Amanjit Gill    schedule 25.12.2017