усилване на сериализацията срещу буферите на протокола на 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 само ако надстроим и клиента, и сървъра в lockstep. (Това е доста предизвикателство в среда, в която нямате пълен контрол върху клиентите си).
  • Boost идва в пакет като една голяма библиотека със споделени части и както кодът за сериализиране, така и другите части на библиотеката за усилване (напр. shared_ptr) може да се използват в един и същи файл, не мога да надстроя никое части от boost, защото не мога да надстроя boost.serialization. Не съм сигурен дали е възможно/безопасно/разумно да се опитваме да свържем множество версии на boost в един изпълним файл или дали имаме бюджета/енергията да преработим битове, които трябва да останат в по-стара версия на boost, в отделна изпълним файл (DLL в нашия случай).
  • Старата версия на boost, на която сме останали, не поддържа най-новата версия на компилатора, който използваме, така че също сме останали на стара версия на компилатора.

Изглежда, че Google всъщност публикува кабелния формат на буферите на протокола, а Wikipedia описва ги като съвместими напред, обратно съвместими (въпреки че мисля, че Wikipedia има предвид по-скоро версията на данни отколкото версията на библиотеката на буфера на протокола). Въпреки че нито едно от тях не е гаранция за съвместимост напред, ми изглежда като по-силна индикация.

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

Бележка под линия: безсрамна приставка за свързан отговор от мен.

person bacar    schedule 25.11.2011
comment
FYI: 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 контейнери.
  • свойствата на записаните данни зависят от избраните потоци (напр. endian, компресиран).

Протоколни буфери

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

Boost serialization е библиотека за конвертиране на обект в сериализиран поток от данни. Протоколните буфери вършат същото нещо, но вършат и друга работа вместо вас (като създаване на версии и размяна на крайния ред). Boost сериализацията е по-проста за "малки прости задачи". Протоколните буфери вероятно са по-добри за "по-голяма инфраструктура".

РЕДАКТИРАНЕ: 24-11-10: Добавено "автоматично" към BS версиите.

person Nick    schedule 07.06.2010
comment
Хм ... това изглежда не е точно правилно, тъй като BS има версии и доколкото знам проблемите с endian зависят от това кой формат за сериализация използвате. - person Martin Ba; 24.11.2010
comment
Добре, не поддържа автоматично. Трябва изрично да вградите версия във вашия код за сериализация, сериализаторът няма да го направи вместо вас. - person Nick; 24.11.2010
comment
boost сериализацията включва версия на данни от самото начало. Това е по подразбиране и автоматично. Ако не искате някои типове данни да бъдат версионирани, можете да ги деактивирате за всеки тип. Но като цяло това почти никога не се прави. - 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 Сериализация:

Той НАИСТИНА позволява поддържането на версиране на данни .

Ако имате нужда от компресия - използвайте компресиран поток.

Може да обработва endian суапинг между платформи, тъй като кодирането може да бъде текстово, двоично или 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)
}

Обърнете внимание на <. Освен това в повечето инструменти 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) инструменти.

Особено ми харесва широкият избор от двоични и текстови формати. Това го прави изключително удобен в някои проекти. Списъкът с кабелни формати в момента включва:

  • BER (двоичен)
  • PER (двоичен, подравнен и неподравнен. Това е изключително битово ефективно. Например и INTEGER, ограничено между 0 и 15, ще заемат само 4 bits на проводника)
  • OER
  • DER (друга двоична)
  • XML (също XER)
  • JSON (чисто нов, поддръжката на инструмента все още се разработва)

плюс други.

Забележете последните две? Да, можете да дефинирате структури от данни в ASN.1, да генерирате код и да излъчвате/консумирате съобщения в XML и JSON. Не е зле за технология, която започна през 80-те години.

Версионирането се извършва различно от GPB. Можете да разрешите разширения:

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

Това означава, че на по-късна дата мога да добавя към Foo и по-старите системи, които имат тази версия, все още могат да работят (но имат достъп само до полето bearing).

Оценявам ASN.1 много високо. Справянето с това може да е трудно (инструментите може да струват пари, генерираният код не е непременно красив и т.н.). Но ограниченията са наистина фантастична функция, която ми спестява цял тон сърдечна болка отново и отново. Кара разработчиците да хленчат много, когато енкодерите/декодерите съобщават, че са генерирали данни за duff.

Други връзки:

Наблюдения

За споделяне на данни:

  • Подходите за първи код (напр. Boost сериализация) ви ограничават до оригиналния език (напр. 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), но страдат от неравномерна поддръжка на инструменти.
    • Например xsd.exe на Microsoft активно игнорира ограниченията в 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 трябва да се вземе под внимание, зърнени култури може да са алтернатива.

person Amanjit Gill    schedule 25.12.2017