Respuesta

29

He jugado un poco con ambos sistemas, nada serio, solo algunas cosas simples de hack, pero sentí que hay una diferencia real en cómo se supone que debes usar las bibliotecas.

Con boost :: serialización, primero escribe sus propias estructuras/clases y luego agrega los métodos de archivo, pero aún le quedan algunas clases bastante "delgadas", que se pueden usar como miembros de datos, heredados, lo que sea.

Con búferes de protocolo, la cantidad de código generado incluso para una estructura simple es bastante considerable, y las estructuras y el código generados están más destinados a funcionar y utilizan la funcionalidad de búfers de protocolo para transportar datos hacia y desde tus propias estructuras internas.

+2

Muy a menudo, no es necesario transportar datos hacia y desde sus propias estructuras internas; puede poblar esas estructuras directamente con los búferes de protocolo. Son esencialmente clases de valores, tienen semántica de movimiento y funcionan muy bien con las colecciones STL y Boost. –

5

Nunca implementé nada usando la biblioteca de boost, pero encontré que Google protobuff es más pensado, y el código es mucho más limpio y fácil de leer. Sugiero que eche un vistazo a los distintos idiomas con los que desea utilizarlo y lea el código y la documentación, y tome una decisión.

La única dificultad que tuve con los protobufs fue que denominaron a una función muy utilizada en su código generado GetMessage(), que por supuesto está en conflicto con la macro Win32 GetMessage.

Todavía recomiendo protobufs. Son muy útiles.

+0

Voy a +1 cuando se restaure mi límite. Gracias por mencionar el obstáculo 'GetMessage'. Algo para pensar ... – Anthony

14

No tengo experiencia con la serialización de impulso, pero he usado búferes de protocolo. Me gustan mucho los búferes de protocolo. Tenga en cuenta lo siguiente (lo digo con sin conocimiento de impulso).

  • búferes de protocolo son muy eficientes por lo que no imagino que ser un problema grave vs impulso.
  • Los búferes de protocolo proporcionan una representación intermedia que funciona con otros lenguajes (Python y Java ... y más en las obras). Si sabes que solo estás usando C++, tal vez impulsar es mejor, pero la opción de utilizar otros idiomas es agradable.
  • Los búferes de protocolo son más como contenedores de datos ... no hay naturaleza orientada a objetos, como la herencia. Piense en la estructura de lo que quiere serializar.
  • Los búferes de protocolo son flexibles porque puede agregar campos "opcionales". Esto básicamente significa que puede cambiar la estructura del búfer de protocolo sin romper la compatibilidad.

Espero que esto ayude.

11

boost.serialization sólo necesita el compilador de C++ y le da un poco de azúcar sintaxis como

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

para guardar la carga. Si C++ es el único idioma que utiliza, debe darle a boost.serialization una oportunidad importante.

Eché un vistazo rápido a los búferes de protocolo de Google. Por lo que veo, diría que no es directamente comparable a boost.serialization. Debe agregar un compilador para los archivos .proto a su cadena de herramientas y mantener los archivos .proto. La API no se integra en C++ como lo hace boost.serialization.

boost.serialization hace el trabajo bien diseñado: para serializar objetos C++ :) OTOH una consulta de API como buffers de protocolo de Google le da más flexibilidad.

Como solo he usado boost.serialization hasta el momento, no puedo hacer ningún comentario sobre la comparación de rendimiento.

41

He usado Boost Serialization durante mucho tiempo y acabo de buscar en búferes de protocolo, y creo que no tienen el mismo propósito. BS (no lo veía venir) guarda sus objetos C++ en una secuencia, mientras que PB es un formato de intercambio desde/desde el que lee.

El modelo de datos de PB es mucho más simple: se obtiene todo tipo de datos y flotantes, cadenas, matrices, estructura básica y eso es todo. BS le permite guardar directamente todos sus objetos en un solo paso.

Eso significa que con BS obtendrá más datos en el cable pero no tiene que reconstruir toda la estructura de sus objetos, mientras que los búferes de protocolo son más compactos pero hay más trabajo por hacer después de leer el archivo. Como su nombre lo indica, uno es para protocolos (paso de datos eficientes desde el punto de vista del lenguaje) y el otro para la serialización (ahorro de objetos sin formato).

Entonces, ¿qué es más importante para usted: eficiencia de velocidad/espacio o código limpio?

16

Boost serialización

  • es una biblioteca para escribir datos en un flujo.
  • no comprime los datos.
  • no es compatible con el control de versiones de datos automáticamente.
  • admite contenedores STL.
  • Las propiedades de los datos escritos dependen de las transmisiones elegidas (por ejemplo, endian, comprimidas).

Protocol Buffers

  • genera código de descripción de la interfaz (es compatible con C++, Python y Java por defecto. C, C# y otros por tercera parte).
  • opcionalmente comprime datos.
  • maneja el control de versiones de datos automáticamente.
  • maneja el intercambio endian entre plataformas.
  • no es compatible con contenedores STL.

La serialización de Boost es una biblioteca para convertir un objeto en una secuencia serializada de datos. Los búferes de protocolo hacen lo mismo, pero también hacen otro trabajo para usted (como el control de versiones y el intercambio de endian). La serialización de Boost es más simple para "pequeñas tareas simples". Los búferes de protocolo son probablemente mejores para una "infraestructura más grande".

EDITAR: 24-11-10: Se agregó "automáticamente" a las versiones de BS.

+1

Hmm ... esto parece no ser exactamente correcto ya que BS tiene control de versiones y, por lo que yo sé, los problemas endian dependen del formato de serialización que use. –

+0

Ok, no es compatible automáticamente. Tiene que crear versiones explícitamente en su código de serialización, el serializador no lo hará por usted. – Nick

+1

serialización impulso ha incluido el control de versiones de datos desde el principio. Es el predeterminado y automático. Si no desea que se versione algún tipo de datos, puede deshabilitarlo tipo por tipo. Pero generalmente esto casi nunca se hace. –

7

Corrección anteriormente (supongo que esto es that answer) sobre serialización Boost:

sí permite apoyar data versioning.

Si necesita compresión, use un flujo comprimido.

Puede manejar el intercambio endian entre plataformas ya que la codificación puede ser de texto, binario o XML.

24

Hay un par de preocupaciones adicionales con boost.serialization que agregaré a la mezcla. Advertencia: no tengo ninguna experiencia directa con los búferes de protocolo más allá de rozar los documentos.

Tenga en cuenta que si bien creo que boost, y boost.serialization, es genial en lo que hace, he llegado a la conclusión de que los formatos de archivo predeterminados que viene no son una gran opción para un formato de conexión.

Es importante distinguir entre las versiones de la clase (como se ha mencionado en otras respuestas, boost.serialization tiene algún apoyo para los datos de versiones) y la compatibilidad entre las diferentes versiones de la biblioteca serialización.

Versiones más recientes de boost.serialization may not generate archives that older versions can deserialize. (lo contrario no es cierto: las versiones más nuevas siempre están destinadas a deserializar los archivos creados por versiones anteriores). Esto ha dado lugar a los siguientes problemas para nosotros:

  • Tanto nuestro software cliente servidor & crear objetos serializados que el otro consume por lo que sólo puede moverse a una nueva boost.serialization si aumentamos el cliente y el servidor al mismo ritmo . (Esto es todo un desafío en un entorno donde no tienes el control total de tus clientes).
  • Boost viene incluido como una gran biblioteca con partes compartidas, y tanto el código de serialización como otras partes de la biblioteca de refuerzo (por ejemplo, shared_ptr) pueden estar en uso en el mismo archivo, no puedo actualizar partes de impulso porque no puedo actualizar boost.serialization. No estoy seguro si es posible/seguro/sensato intentar vincular múltiples versiones de refuerzo en un único ejecutable, o si tenemos el presupuesto/energía para refactorizar los bits que deben permanecer en una versión anterior de impulsar en un archivo separado ejecutable (DLL en nuestro caso).
  • La versión anterior de boost en la que estamos trabajados no es compatible con la última versión del compilador que usamos, por lo que también estamos atascados en una versión anterior del compilador.

Google parece que en realidad publish the protocol buffers wire format, y los describe como Wikipedia forwards-compatible, backwards-compatible (aunque creo que Wikipedia se refiere a los datos de versiones en lugar de búfer de protocolo de control de versiones de la biblioteca). Si bien ninguno de estos es una garantía de compatibilidad con versiones anteriores, parece una indicación más fuerte para mí.

En resumen, yo preferiría un conocido, el formato de alambre publicada como búferes de protocolo cuando no tengo la capacidad de actualizar el servidor cliente & al mismo paso.

Nota al pie: enchufe desvergonzado para un related answer por mí.

+6

FYI: 2.5 años después, ahora tengo mucha experiencia directa con los buffers de protocolo, y estoy de acuerdo con mis comentarios anteriores. – bacar

2

Como con casi todo en ingeniería, mi respuesta es ... "depende."

Ambas son tecnologías probadas y bien probadas. Ambas tomarán sus datos y los convertirán en algo amigable para enviar a otro lugar. Ambos serán probablemente lo suficientemente rápidos, y si realmente está contando un byte aquí o allá, usted ' Probablemente no va a estar contento con ninguno (seamos sinceros, ambos paquetes creados serán una pequeña fracción de XML o JSON).

Para mí, todo se reduce al flujo de trabajo y si necesita algo más que C++ en el otro extremo

Si primero quiere averiguar el contenido de su mensaje y está construyendo un sistema desde cero, use el protocolo Buffers. Puede pensar en el mensaje de manera abstracta y luego au para generar el código en el idioma que desee (los complementos de terceros están disponibles para casi todo). Además, encuentro que la colaboración se simplifica con Protocol Buffers. Simplemente envío un archivo .proto y luego el otro equipo tiene una idea clara de qué datos se están transfiriendo. Tampoco les impongo nada. Si quieren usar Java, ¡adelante!

Si ya he construido una clase en C++ (y esto ha sucedido más de las veces) y quiero enviar esos datos por cable ahora, la Serialización de Boost obviamente tiene muchísimo sentido (especialmente cuando ya tengo un Aumentar la dependencia en otro lugar).

0

Puede utilizar la serialización boost en conjunción estrecha con sus objetos de dominio "reales", y serializar la jerarquía completa de objetos (herencia). Protobuf no es compatible con la herencia, por lo que deberá usar la agregación. La gente argumenta que Protobuf debe usarse para DTO (objetos de transferencia de datos), y no para objetos de dominio central. He usado tanto boost :: serialization y protobuf. El rendimiento de boost :: serialización debe tenerse en cuenta, cereal podría ser una alternativa.

0

Sé que esta es una pregunta más antigua ahora, ¡pero pensé en tirar mis 2 peniques!

Con impulso, tienes la oportunidad de escribir algunas validaciones de datos en tus clases; esto es bueno porque la definición de datos y las verificaciones de validez están todas en un solo lugar.

Con GPB, lo mejor que puede hacer es poner comentarios en el archivo .proto y esperar contra toda esperanza que quien lo esté usando lo lea, lo preste atención e implemente los controles de validez.

No hace falta decir que esto es improbable y poco confiable si confía en alguien más al otro lado de la red para hacer esto con el mismo vigor que uno mismo. Además, si cambian las restricciones de validez, se deben planear, coordinar y llevar a cabo varios cambios de código.

Por lo tanto, considero que GPB es inapropiado para desarrollos donde hay pocas oportunidades de reunirse regularmente y hablar con todos los miembros del equipo.

== == EDITAR

El tipo de cosas que quiero decir es lo siguiente:

message Foo 
{ 
    int32 bearing = 1; 
} 

Ahora ¿quién puede decir lo que el rango válido de bearing es? Podemos tener

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

Pero eso depende de que alguien más lea esto y escriba el código para ello.Por ejemplo, si edita y la restricción se convierte en:

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

son completamente dependientes de todos los que han utilizado este .proto la actualización de su código. Eso no es confiable y costoso.

Al menos con la serialización de Boost está distribuyendo una única clase de C++, y eso puede tener comprobaciones de validez de datos integradas en él. Si esas restricciones cambian, entonces nadie más necesita hacer otro trabajo que no sea asegurarse de que estén usando la misma versión del código fuente que usted.

Alternativa

hay una alternativa: ASN.1. Esto es antiguo, pero tiene algunas cosas realmente, realmente útiles:

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

Tenga en cuenta la restricción. Así que cada vez que alguien consume este archivo .asn, genera el código, terminan con el código que comprobará automáticamente que bearing se encuentra entre 0 y 359. Si actualiza el archivo .asn,

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

todo lo que necesitan hacer es recompilar No se requieren otros cambios de código.

También puede hacer:

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

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

Nota del <. Y también en la mayoría de las herramientas, el bearingMin y bearingMax pueden aparecer como constantes en el código generado. Eso es extremadamente útil.

Las restricciones pueden ser muy elaborados:

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

mirada en el capítulo 13 de este PDF; es increíble lo que puedes hacer;

Las matrices pueden estar limitadas también:

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á pasado de moda, pero sigue siendo activamente desarrollado, ampliamente utilizado (su teléfono móvil lo utiliza mucho), y mucho más flexible que la mayoría de otras tecnologías de serialización . La única deficiencia que puedo ver es que no hay un generador de código decente para Python. Si está usando C/C++, C#, Java, ADA, entonces cuenta con una buena combinación de herramientas gratuitas (C/C++, ADA) y comerciales (C/C++, C#, JAVA).

Me gusta especialmente la gran variedad de formatos de alambre binarios y basados ​​en texto. Esto lo hace extremadamente conveniente en algunos proyectos. La lista wireformat incluye actualmente:

  • BER (binario)
  • PER (binario, alineados y no alineados Este es ultra poco eficiente..Por ejemplo, y INTEGER limitado entre 0 y 15 ocupará solamente 4 bits en el cable)
  • REA
  • DER (otro binario)
  • XML (también XER)
  • JSON (a estrenar, soporte de herramientas es aún en desarrollo)

más otros.

¿Tenga en cuenta los dos últimos? Sí, puede definir estructuras de datos en ASN.1, generar código y emitir/consumir mensajes en XML y JSON. No está mal para una tecnología que comenzó en la década de 1980.

Las versiones se realizan de forma diferente a GPB. Puede permitir extensiones:

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

Esto significa que en una fecha posterior que puedo añadir a Foo, y los sistemas más antiguos que tengan esta versión todavía puede trabajar (pero sólo pueden acceder al campo bearing).

Califico ASN.1 muy altamente. Puede ser difícil de manejar (las herramientas pueden costar dinero, el código generado no es necesariamente hermoso, etc.). Pero las limitaciones son una característica realmente fantástica que me ha ahorrado una tonelada de dolor de corazón una y otra vez. Hace que los desarrolladores se quejen mucho cuando los codificadores/decodificadores informan que generaron datos duff.

Otros enlaces:

Observaciones

para compartir datos:

  • Código primeros enfoques (por ejemplo, Impulsar la serialización) que restringir al idioma original (por ejemplo, C++), o le obligan a hacer un montón de trabajo extra en otro idioma
  • esquema primero es mejor, pero
    • muchos de éstos dejan grandes lagunas en el contrato compartido (es decir, sin restricciones). GPB es molesto en este sentido, porque de lo contrario es muy bueno.
    • Algunos tienen restricciones (por ejemplo, XSD, JSON), pero sufren compatibilidad con herramientas irregulares.
    • Por ejemplo, el xsd.exe de Microsoft ignora activamente las restricciones en los archivos xsd (la excusa de MS es realmente débil). XSD es bueno (desde el punto de vista de las limitaciones), pero si no puede confiar en que el otro use una buena herramienta XSD que lo haga valer, el valor de XSD disminuirá
    • Los validadores JSON están bien, pero no haga nada para ayudarlo a formar el JSON en primer lugar, y no se llama automáticamente.No hay garantía de que alguien le envíe un mensaje JSON y lo haya ejecutado a través de un validador. Debes recordar validarlo tú mismo.
    • Todas las herramientas ASN.1 parecen implementar la comprobación de restricciones.

Así que para mí, ASN.1 lo hace. Es el menos probable que resulte en que alguien más cometa un error, porque es el que tiene las características correctas y las herramientas aparentemente intentan implementar completamente esas características, y es lo suficientemente neutral para la mayoría de los propósitos.

Para ser sincero, si GPB agregó un mecanismo de restricciones que sería el ganador. XSD está cerca pero las herramientas son casi universalmente basura. Si hubiera generadores de código decentes de otros idiomas, el esquema JSON sería bastante bueno.

Si GPB tenía restricciones añadidas (nota: esto no cambiaría ninguno de los formatos de conexión), sería el que recomendaría a todos para casi cualquier propósito. Aunque el UPER de ASN.1 es muy útil para los enlaces de radio.

Cuestiones relacionadas