Вопрос по c++, performance – повысить сериализацию против буферов протокола Google? [закрыто]

62

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

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

Ваш Ответ

11   ответов
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)
}

Обратите внимание<, Кроме того, в большинстве инструментов 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 (binary) PER (binary, aligned and unaligned. This is ultra bit efficient. For example, and INTEGER constrained between 0 and 15 will take up only 4 bits on the wire) OER DER (another binary) XML (also XER) JSON (brand new, tool support is still developing)

плюс другие.

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

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

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

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

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

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

Good intro Open source C/C++ compiler Open source compiler, does ADA too AFAIK Commercial, good Commercial, good Try it yourself online

Observations

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

Code first approaches (e.g. Boost serialisation) restrict you to the original language (e.g. C++), or force you to do a lot of extra work in another language 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. Some have constraints (e.g. XSD, JSON), but suffer patchy tool support. For example, Microsoft's xsd.exe actively ignores constraints in xsd files (MS's excuse is truly feeble). XSD is good (from the constraints point of view), but if you cannot trust the other guy to use a good XSD tool that enforces them for him/her then the worth of XSD is diminished JSON validators are ok, but they do nothing to help you form the JSON in the first place, and aren't automatically called. There's no guarantee that someone sending you JSON message have run it through a validator. You have to remember to validate it yourself. ASN.1 tools all seem to implement the constraints checking.

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

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

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

25

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

Note that while I think boost, and boost.serialization, is great at what it does, I have come to the conclusion that the default archive formats it comes with are not a great choice for a wire format.

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

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

Both our client & server software create serialized objects that the other consumes, so we can only move to a newer boost.serialization if we upgrade both client and server in lockstep. (This is quite a challenge in an environment where you don't have full control of your clients). Boost comes bundled as one big library with shared parts, and both the serialization code and the other parts of the boost library (e.g. shared_ptr) may be in use in the same file, I can't upgrade any parts of boost because I can't upgrade boost.serialization. I'm not sure if it's possible/safe/sane to attempt to link multiple versions of boost into a single executable, or if we have the budget/energy to refactor out bits that need to remain on an older version of boost into a separate executable (DLL in our case). The old version of boost we're stuck on doesn't support the latest version of the compiler we use, so we're stuck on an old version of the compiler too.

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

В итоге,I would prefer a well-known, published wire format как буферы протокола, когда у меня нет возможности обновить клиент & amp; Сервер в шаге.

Сноска: бесстыдная вилка длясвязанный ответ мной.

К вашему сведению: 2,5 года спустя у меня есть большой опыт работы с буферами протоколов, и я поддерживаю свои замечания выше.
Что означает «старая версия boost, на которой мы застряли, не поддерживает последнюю версию используемого нами компилятора»? Использует ли Boost нестандартные языковые расширения или почему это произошло?
Хороший вопрос. Я думаю да & # x2014; например, я бы предположил, что boost.thread и boost.interprocess используют (или использовали) специфичные для платформы API для реализации функций, которые могут оказаться невозможными для реализации мобильно. Кроме того, соответствие стандартов компиляторам варьируется в зависимости от версии, так что то, что работало, например, MSVC 2005 может не работать / компилироваться с более поздними версиями. Boost.org документирует, какие компиляторы работают:boost.org/doc/libs/1_67_0/libs/log/doc/html/log/…
5

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

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

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

I +1 +1, когда мой лимит восстановлен. Спасибо за упоминаниеGetMessage препятствие. Что-то думать о...
7

этот ответ) о повышении сериализации:

Это позволяет поддерживатьуправление версиями данных.

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

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

2

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

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

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

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

0

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

16

Boost Serialisation

is a library for writing data into a stream. does not compress data. does not support data versioning automatically. supports STL containers. properties of data written depend on streams chosen (e.g. endian, compressed).

Protocol Buffers

generates code from interface description (supports C++, Python and Java by default. C, C# and others by 3rd party). optionally compresses data. handles data versioning automatically. handles endian swapping between platforms. does not support STL containers.

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

РЕДАКТИРОВАТЬ: 24-11-10: добавлено & quot; автоматически & quot; в BS версии.

Хм ... кажется, что это не совсем правильно, поскольку у BS есть управление версиями, и, насколько я знаю, проблемы с порядком байтов зависят от того, какой формат сериализации вы используете.
Хорошо, он не поддерживает автоматически. Вы должны явно встроить версионность в свой код сериализации, сериализатор не сделает этого за вас.
ускоренная сериализация включала управление версиями данных с самого начала. Это по умолчанию и автоматически. Если вы не хотите, чтобы какой-либо тип данных был версионным, вы можете отключить его для каждого типа. Но, как правило, это почти никогда не делается.
Сжатие данных с надстройкой очень легко добавить в смесь:stackoverflow.com/questions/1753469/…
Сжатие данных, как правило, осуществляется с помощью композиции iostream. Это не является частью расширенной сериализации, потому что это будет избыточным.
14

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

Protocol buffers are very efficient so I don't imagine that being a serious issue vs. boost. Protocol buffers provide an intermediate representation that works with other languages (Python and Java... and more in the works). If you know you're only using C++, maybe boost is better, but the option to use other languages is nice. Protocol buffers are more like data containers... there is no object oriented nature, such as inheritance. Think about the structure of what you want to serialize. Protocol buffers are flexible because you can add "optional" fields. This basically means you can change the structure of protocol buffer without breaking compatibility.

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

43

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

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

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

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

29

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

С boost :: serialization вы сначала пишете свои собственные структуры / классы, а затем добавляете методы архивации, но у вас все еще остается довольно симпатичный & quot; slim & quot; классы, которые могут использоваться в качестве членов данных, наследоваться, что угодно.

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

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

который дает вам синтаксический сахар

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

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

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

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

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

Похожие вопросы