61

У кого-нибудь, у кого есть опыт работы с этими библиотеками, есть какие-либо комментарии по поводу того, что они предпочитают? Были ли какие-либо различия в производительности или трудности с использованием?повысить сериализацию против буферов протокола Google?

+4

Это близко к дубликату http://stackoverflow.com/questions/321619/c-serialization-performance, поэтому может быть полезно также – Laserallan

ответ

29

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

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

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

+2

Очень часто вам не нужно передавать данные в собственные внутренние структуры и из них - вы можете заполнить эти структуры напрямую буферами протоколов. Они по сути являются классами ценности, они имеют семантику перемещения, и они прекрасно сочетаются с коллекциями STL и Boost. –

5

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

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

Я по-прежнему очень рекомендую протобуфы. Они очень полезны.

+0

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

14

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

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

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

11

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, пока не могу комментировать сравнение производительности.

41

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

PB Datamodel упрощен: вы получаете все виды ints и floats, строки, массивы, базовую структуру, и это в значительной степени это. BS позволяет вам сразу сохранить все ваши объекты за один шаг.

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

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

16

подталкивания Сериализация

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

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

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

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

EDIT: 24-11-10: Добавлено «автоматически» для версии BS.

+1

Хм ... это, похоже, не совсем корректно, так как у BS есть управление версиями, и насколько я знаю, проблемы с endian зависят от того, какой формат сериализации вы используете. –

+0

Хорошо, это не поддерживается автоматически. Вы должны явно создать версию в свой код сериализации, сериализатор не сделает это за вас. – Nick

+1

Включение сериализации включает в себя управление версиями данных с самого начала. Это по умолчанию и автоматически. Если вы не хотите, чтобы какой-либо тип данных был версией, вы можете отключить его по типу по типу. Но в целом это почти никогда не делается. –

7

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

Оно позволяет поддерживать data versioning.

Если вам требуется сжатие - используйте сжатый поток.

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

24

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

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

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

Новые версии boost.serialization may not generate archives that older versions can deserialize. (обратное неверно: более новые версии всегда предназначены для десериализации архивов, сделанных более старыми версиями). Это привело к следующим проблемам для нас:

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

Google, кажется, на самом деле publish the protocol buffers wire format, и Википедия описывает их как forwards-compatible, backwards-compatible (хотя я думаю, Википедия со ссылкой на данные управления версиями, а не буфера протокола библиотеки версий). Хотя ни одна из них не является гарантией передовой совместимости, это кажется более сильным показателем для меня.

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

Сноска: бесстыдная штепсельная вилка для related answer от меня.

+6

FYI: через 2,5 года у меня теперь есть много непосредственного опыта работы с буферами протоколов, и я согласен с моими замечаниями выше. – bacar

2

Как и почти все в технике, мой ответ ... «это зависит.«

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

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

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

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

0

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

0

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

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

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

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

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

== EDIT ==

вид вещи, я имею в виду это:

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++ и можете иметь встроенные в него проверки достоверности данных. Если эти ограничения меняются, то никто другой не нуждается в какой-либо работе, кроме как убедиться, что они используют ту же версию исходного кода, что и вы.

Alternative

Существует альтернатива: 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) 
} 

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

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

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) инструментов.

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

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

plus others.

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

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

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

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

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

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

Наблюдения

Для обмена данными:

  • Код первые подходы (например, Повышение сериализации) ограничивает вас на языке оригинала (например, C++), или заставить вас сделать много дополнительной работы на другом языке
  • схемы первого лучше, но
    • Многие из них оставляют большие пробелы в (т.е. никаких ограничений). В этом отношении ГПБ раздражает, потому что в противном случае это очень хорошо.
    • Некоторые из них имеют ограничения (например, XSD, JSON), но страдают от неоднородной поддержки инструмента.
    • Например, xsd.exe от Microsoft активно игнорирует ограничения в файлах xsd (оправдание MS действительно слабое). XSD хорош (с точки зрения ограничений), но если вы не можете доверять другому парню, чтобы использовать хороший инструмент XSD, который их применяет для него/нее, то стоимость XSD уменьшается
    • Валидаторы JSON в порядке, но они не делайте ничего, чтобы помочь вам сформировать JSON в первую очередь и не вызываются автоматически.Нет никакой гарантии, что кто-то, отправляющий вам сообщение JSON, проведет его через валидатор. Вы должны помнить, чтобы проверить его самостоятельно.
    • Все инструменты ASN.1, похоже, реализуют проверку ограничений.

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

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

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

Смежные вопросы