web-dev-qa-db-fra.com

augmenter la sérialisation vs tampons de protocole google?

Quelqu'un qui a de l'expérience avec ces bibliothèques a-t-il des commentaires sur celle qu'elle préfère? Y a-t-il eu des différences de performances ou des difficultés d'utilisation?

62
0xC0DEFACE

J'ai un peu joué avec les deux systèmes, rien de grave, juste quelques trucs simples, mais j'ai senti qu'il y avait une réelle différence dans la manière dont vous êtes censé utiliser les bibliothèques.

Avec boost :: serialization, vous écrivez d’abord vos propres structures/classes, puis vous ajoutez les méthodes d’archivage, mais il vous reste encore quelques jolies classes "minces", qui peuvent être utilisées en tant que membres de données, héritées, peu importe.

Avec les tampons de protocole, la quantité de code généré, même pour une structure simple, est assez substantielle, et les structures et le code générés sont plus destinés à être utilisés, et vous utilisez la fonctionnalité des tampons de protocole pour transporter des données de et vers vos propres structures internes. .

29
Magnus Österlind

J'utilise la sérialisation Boost depuis longtemps et je viens juste de creuser dans des tampons de protocole, et je pense qu'ils n'ont pas exactement le même objectif. BS (qui n'a pas vu cela venir) enregistre vos objets C++ dans un flux, alors que PB est un format d'échange que vous lisez vers/depuis.

Le modèle de données de PB est beaucoup plus simple: vous obtenez toutes sortes d’intégrations et de flottants, de chaînes, de tableaux, de structures de base et c’est à peu près tout. BS vous permet de sauvegarder directement tous vos objets en une seule étape.

Cela signifie qu'avec BS, vous obtenez plus de données sur le réseau mais vous n'avez pas à reconstruire toute la structure de vos objets, alors que les tampons de protocole sont plus compacts, mais qu'il reste encore du travail à faire après la lecture de l'archive. Comme son nom l'indique, l'un concerne les protocoles (transmission de données efficace en termes d'espace et agnostique sur la langue), l'autre la sérialisation (sauvegarde des objets à mémoire de forme).

Alors, qu'est-ce qui est le plus important pour vous: efficacité de la vitesse/espace ou code propre?

43
ndfred

Il y a quelques problèmes supplémentaires avec boost.serialization que je vais ajouter au mélange. Mise en garde: Je n'ai aucune expérience directe avec les tampons de protocole au-delà de l'écrémage des documents.

Notez que même si je pense que boost et boost.serialization sont excellents, je suis parvenu à la conclusion que les formats d'archivage par défaut fournis ne constituent pas un excellent choix pour un format filaire.

Il est important de distinguer les versions de de votre classe (comme indiqué dans d’autres réponses, boost.serialization prend en charge le contrôle de version des données) et la compatibilité entre les différentes versions de bibliothèque de sérialisation .

Nouvelles versions de boost.serialization ne peut pas générer d'archives que des versions plus anciennes peuvent désérialiser . (l'inverse n'est pas vrai: nouvelles versions sont toujours destinés à désérialiser les archives créées par des versions antérieures). Cela a conduit aux problèmes suivants pour nous:

  • Nos logiciels client et serveur créent tous deux des objets sérialisés que l'autre consomme. Nous ne pouvons donc passer à une nouvelle boost.serialization que si nous mettons à niveau le client et le serveur en même temps. (C'est tout un défi dans un environnement où vous n'avez pas le contrôle total de vos clients).
  • Boost est fourni avec une grande bibliothèque avec des parties partagées. Le code de sérialisation et les autres parties de la bibliothèque boost (par exemple shared_ptr) peuvent être utilisés dans le même fichier. Je ne peux pas mettre à niveau parties de boost car je ne peux pas mettre à jour boost.serialization. Je ne sais pas s'il est possible/sûr/sain de tenter de lier plusieurs versions de boost dans un seul exécutable, ou si nous avons le budget/l'énergie nécessaires pour refactoriser les bits qui doivent rester dans une version plus ancienne de boost dans un fichier séparé. exécutable (DLL dans notre cas).
  • L'ancienne version de boost sur laquelle nous sommes bloqués ne supporte pas la dernière version du compilateur que nous utilisons, nous sommes donc également bloqués sur une ancienne version du compilateur.

Google semble réellement publier le format filaire des tampons de protocole , et Wikipedia les décrit comme compatible avec la version antérieure, compatible avec la version antérieure (bien que je pense que Wikipedia parle de versioning des données plutôt que du protocole versioning de la bibliothèque de tampons). Bien qu’aucune de celles-ci ne soit une garantie de compatibilité en aval, cela me semble une indication plus forte.

En résumé, , je préférerais un format de câble bien connu et publié comme les tampons de protocole lorsque je n'ai pas la possibilité de mettre à niveau le client et le serveur en mode bloqué. .

Note de bas de page: fiche éhontée pour un réponse connexe par moi.

26
bacar

Sérialisation Boost

  • est une bibliothèque pour écrire des données dans un flux.
  • ne compresse pas les données.
  • ne prend pas automatiquement en charge le versioning des données. 
  • prend en charge les conteneurs STL.
  • les propriétés des données écrites dépendent des flux choisis (par exemple, endian, compressé).

Tampons de protocole

  • génère du code à partir de la description de l'interface (prend en charge les langages C++, Python et Java par défaut. C, C # et autres par des tiers).
  • compresse éventuellement les données.
  • gère le versioning des données automatiquement.
  • gère les échanges finaux entre plates-formes.
  • ne prend pas en charge les conteneurs STL.

La sérialisation Boost est une bibliothèque permettant de convertir un objet en un flux de données sérialisé. Les tampons de protocole font la même chose, mais font également un autre travail pour vous (comme la gestion de version et l'échange). La sérialisation Boost est plus simple pour les "petites tâches simples". Les tampons de protocole sont probablement meilleurs pour une "infrastructure plus grande".

EDIT: 24-11-10: Ajouté "automatiquement" à la gestion des versions de BS.

16
Nick

Je n'ai aucune expérience de la sérialisation boost, mais j'ai utilisé des tampons de protocole. J'aime beaucoup les tampons de protocole. Gardez ceci à l'esprit (je le dis avec aucune connaissance de boost).

  • Les tampons de protocole sont très efficaces, donc je ne suis pas imaginez être un problème sérieux par rapport au boost.
  • Les tampons de protocole fournissent une représentation intermédiaire qui fonctionne avec d'autres langages (Python et Java ... et plus encore dans les travaux). Si vous savez que vous utilisez uniquement le C++, peut-être que boost est préférable, mais l'option d'utiliser d'autres langages est Nice.
  • Les tampons de protocole ressemblent davantage à des conteneurs de données ... il n'y a pas de nature orientée objet, telle que l'héritage. Réfléchissez à la structure de ce que vous voulez sérialiser.
  • Les tampons de protocole sont flexibles car vous pouvez ajouter des champs "facultatifs". Cela signifie fondamentalement que vous pouvez modifier la structure du tampon de protocole sans interrompre la compatibilité.

J'espère que cela t'aides.

14
Tom

boost.serialization a juste besoin du compilateur C++ et vous donne un peu de sucre syntaxique comme

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

pour sauvegarder et charger. Si C++ est le seul langage que vous utilisez, vous devriez donner un sérieux coup de pouce à boost.serialization. 

J'ai jeté un coup d'oeil rapide aux tampons de protocole de Google. D'après ce que je vois, je dirais que ce n'est pas directement comparable à boost.serialization. Vous devez ajouter un compilateur pour les fichiers .proto à votre chaîne d'outils et gérer les fichiers .proto eux-mêmes. L'API ne s'intègre pas dans C++, contrairement à boost.serialization. 

boost.serialization fait très bien son travail: sérialiser des objets C++:.

Comme je n’ai jusqu’à présent utilisé que boost.serialization, je ne peux pas commenter la comparaison des performances. 

11
Maik Beckmann

Correction à la précédente (supposez que c'est cette réponse ) à propos de la sérialisation Boost:

Cela permet de supporter le versioning des données .

Si vous avez besoin de compression, utilisez un flux compressé.

Peut gérer les échanges finaux entre plates-formes car le codage peut être texte, binaire ou XML.

7
Robert Ramey

Je n'ai jamais implémenté quoi que ce soit en utilisant la bibliothèque de boost, mais j'ai trouvé le protobuff de Google plus réfléchi, et le code est beaucoup plus propre et plus facile à lire. Je suggérerais de jeter un coup d'œil sur les différentes langues avec lesquelles vous voulez l'utiliser, de lire le code et la documentation, puis de vous décider.

La seule difficulté que je rencontrais avec les protobufs a été de nommer une fonction très utilisée dans leur code généré GetMessage (), ce qui bien sûr est en conflit avec la macro Win32 GetMessage. 

Je recommanderais toujours fortement les protobufs. Ils sont très utiles.

5
i_am_jorf

Comme dans presque tous les domaines de l'ingénierie, ma réponse est… "ça dépend."

Les deux technologies sont bien testées et validées. Les deux vont prendre vos données et les transformer en quelque chose de convivial pour envoyer quelque part. Les deux seront probablement assez rapides, et si vous comptez vraiment un octet ici ou là, vous ne serez probablement pas satisfait non plus (les deux paquets créés ne seront en réalité qu'une petite fraction de XML ou JSON).

Pour moi, tout dépend du flux de travail et de la question de savoir si vous avez besoin d'autre chose que de C++ à l'autre bout.

Si vous voulez d'abord comprendre le contenu de votre message et que vous construisez un système à partir de rien, utilisez des tampons de protocole. Vous pouvez concevoir le message de manière abstraite, puis générer automatiquement le code dans la langue de votre choix (des plugins tiers sont disponibles pour à peu près tout). De plus, je trouve la collaboration simplifiée avec les tampons de protocole. Je viens d’envoyer un fichier .proto et l’autre équipe a une idée précise des données transférées. Je ne leur impose rien non plus. S'ils veulent utiliser Java, allez-y!

Si j'ai déjà construit une classe en C++ (et cela s'est passé plus souvent qu'autrement) et que je souhaite maintenant envoyer ces données sur le réseau, la sérialisation Boost a évidemment beaucoup de sens (en particulier lorsque j'ai déjà une dépendance Boost ailleurs ).

2
It'sPete

Je sais que c'est une question plus ancienne maintenant, mais je pensais jeter mon 2 pence dedans!

Avec boost, vous aurez l’occasion d’écrire des validations de données dans vos cours; c’est bien parce que la définition des données et les contrôles de validité sont tous au même endroit. 

Avec GPB, le mieux que vous puissiez faire est de mettre des commentaires dans le fichier .proto et d’espérer que ceux qui l’utiliseront le liront, y prêteront attention et mettront en œuvre les contrôles de validité eux-mêmes. 

Inutile de dire que cela est peu probable et peu fiable si vous vous fiez à quelqu'un d'autre à l'autre bout du flux réseau pour le faire avec la même vigueur que vous-même. De plus, si les contraintes sur la validité changent, plusieurs modifications du code doivent être planifiées, coordonnées et effectuées. 

Par conséquent, je considère que GPB est inapproprié pour les développements dans lesquels il est difficile de rencontrer et de discuter régulièrement avec tous les membres de l'équipe. 

== EDIT ==

Le genre de chose que je veux dire est la suivante:

message Foo
{
    int32 bearing = 1;
}

Maintenant, qui peut dire quelle est la plage valide de bearing? Nous pouvons avoir

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

Mais cela dépend de la lecture et de l'écriture du code par quelqu'un d'autre. Par exemple, si vous le modifiez et que la contrainte devient:

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

vous êtes complètement dépendant de tous ceux qui ont utilisé ce fichier .proto pour mettre à jour leur code. C'est peu fiable et coûteux.

Au moins, avec la sérialisation Boost, vous distribuez une seule classe C++ et vous pouvez intégrer des contrôles de validité des données. Si ces contraintes changent, personne d'autre n'est obligé de faire autre chose que de s'assurer qu'il utilise la même version du code source que vous.

Alternative

Il existe une alternative: ASN.1. C'est ancien, mais il y a des choses vraiment très utiles:

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

Notez la contrainte. Ainsi, chaque fois que quelqu'un consomme ce fichier .asn, génère du code, il se retrouve avec un code qui vérifie automatiquement que bearing est compris entre 0 et 359. Si vous mettez à jour le fichier .asn, 

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

tout ce qu'ils doivent faire est de recompiler. Aucun autre changement de code n'est requis.

Vous pouvez aussi faire:

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

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

Notez le <. De plus, dans la plupart des outils, bearingMin et bearingMax peuvent apparaître en tant que constantes dans le code généré. C'est extrêmement utile.

Les contraintes peuvent être assez complexes:

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

Regardez le chapitre 13 dans ce PDF ; C'est incroyable ce que vous pouvez faire.

Les tableaux peuvent aussi être contraints:

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 est démodé, mais reste activement développé, largement utilisé (votre téléphone mobile l’utilise beaucoup) et beaucoup plus flexible que la plupart des autres technologies de sérialisation. La seule lacune que je puisse constater est qu’il n’ya pas de générateur de code décent pour Python. Si vous utilisez C/C++, C #, Java, ADA, vous serez bien servi par une combinaison d'outils gratuits (C/C++, ADA) et commerciaux (C/C++, C #, Java). 

J'aime particulièrement le large choix de formats filaires binaires et textuels. Cela le rend extrêmement pratique dans certains projets. La liste des formats de fil comprend actuellement:

  • BER (binaire) 
  • PER (binaire, aligné et non aligné. Ceci est ultra efficace. Par exemple, et INTEGER contraint entre 0 et 15 ne prendra que 4 bits sur le réseau) 
  • REL 
  • DER (un autre binaire) 
  • XML (également XER) 
  • JSON (flambant neuf, le support des outils est encore en développement)

plus d'autres.

Notez les deux derniers? Oui, vous pouvez définir des structures de données dans ASN.1, générer du code et émettre/consommer des messages au format XML et JSON. Pas mal pour une technologie qui a débuté dans les années 1980.

Le versionnage est effectué différemment de GPB. Vous pouvez autoriser des extensions:

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

Cela signifie qu’à une date ultérieure, je pourrai ajouter Foo et que les anciens systèmes dotés de cette version pourront toujours fonctionner (mais ne pourront accéder qu’au champ bearing).

Je note très haut ASN.1. Cela peut être difficile à gérer (les outils peuvent coûter de l’argent, le code généré n’est pas forcément beau, etc.). Mais les contraintes sont une caractéristique vraiment fantastique qui m’a épargné maintes fois mal au cœur. Les développeurs ont beaucoup de peine à se plaindre lorsque les encodeurs/décodeurs signalent qu'ils ont généré des données duff.

Autres liens:

Observations

Pour partager des données:

  • Les approches de code d'abord (par exemple, la sérialisation Boost) vous restreignent à la langue d'origine (par exemple, C++) ou vous obligent à effectuer beaucoup de travail supplémentaire dans une autre langue.
  • Le schéma en premier est préférable, mais
    • Beaucoup d’entre elles laissent de grandes lacunes dans le contrat de partage (c’est-à-dire qu’il n’ya pas de contrainte). GPB est agaçant à cet égard, car il est par ailleurs très bon.Certains ont des contraintes (par exemple, XSD, JSON), mais souffrent d’un support d’outils variable.
    • Par exemple, xsd.exe de Microsoft ignore activement les contraintes des fichiers xsd (l'excuse de MS est vraiment faible). XSD est bon (du point de vue des contraintes), mais si vous ne pouvez pas faire confiance à votre interlocuteur pour utiliser un bon outil XSD qui le lui impose, la valeur de XSD diminue alors. 
    • Les validateurs JSON sont ok, mais ils ne font rien pour vous aider à former le JSON et ne sont pas appelés automatiquement. Il n'y a aucune garantie que quelqu'un qui vous envoie un message JSON l'ait passé par un validateur. Vous devez vous souvenir de le valider vous-même.
    • Les outils ASN.1 semblent tous implémenter la vérification des contraintes.
    • Donc pour moi, ASN.1 le fait. C’est celui qui est le moins susceptible d’entraîner une erreur par quelqu'un d’autre, car c’est celui qui présente les fonctionnalités adéquates et où les outils s’efforcent apparemment d’implémenter toutes ces fonctionnalités, et il est suffisamment neutre vis-à-vis du langage. 

Pour être honnête, si GPB ajoutait un mécanisme de contraintes, il serait gagnant. XSD est proche mais les outils sont presque universellement nuls. S'il y avait des générateurs de code convenables d'autres langages, le schéma JSON serait plutôt bon.

Si GPB avait des contraintes ajoutées (note: cela ne changerait aucun des formats wire), ce serait celui que je recommanderais à tout le monde pour presque tous les buts. Bien que l'uPER d'ASN.1 soit très utile pour les liaisons radio. 

If GPB had constraints added (note: this would not change any of the wire formats), that'd be the one I'd recommend to everyone for almost every purpose. Though ASN.1's uPER is very useful for radio links.

0
bazza

Vous pouvez utiliser la sérialisation boost en association étroite avec vos objets de domaine "réels" et sérialiser la hiérarchie complète des objets (héritage). Protobuf ne supporte pas l'héritage, vous devrez donc utiliser l'agrégation. Les gens avancent que Protobuf devrait être utilisé pour les objets de transfert de données (DTO) et non pour les objets de domaine principaux eux-mêmes. J'ai utilisé à la fois boost :: serialization et protobuf. La performance de boost :: sérialisation doit être prise en compte, céréales pourrait être une alternative. 

0
Amanjit Gill