2009-02-14 19 views
55

Quiero usar la serialización de objetos para comunicarme a través de la red entre un servidor Mono y clientes de Silverlight. Es muy importante que la serialización sea eficiente en el uso del espacio y bastante rápida, ya que el servidor alojará múltiples juegos en tiempo real.serialización de objetos rápida y compacta en .NET

¿Qué técnica debo usar? BinaryFormatter agrega muchas clases generales a serializadas (Versión, cultura, nombre de clase, nombres de propiedad, etc.) que no se requieren en esta aplicación.

¿Qué puedo hacer para hacer que este espacio sea más eficiente?

+4

D'oh! Llegó una hora tarde ;-p –

Respuesta

66

Puede usar Protocol Buffers. Estoy cambiando todo mi código de serialización de BinaryFormatter con compresión a Protocol Buffers y obtengo muy buenos resultados. Es más eficiente en tiempo y espacio.

Hay dos implementaciones .NET por Jon Skeet y Marc Gravell.

Actualización: Implementación .NET oficial se puede encontrar here.

+0

Gracias. ¡Estas implementaciones también parecen funcionar con Silverlight! –

+2

@Jorge - por cierto, ¿se dio cuenta de que protobuf-net puede engancharse directamente en BinaryFormatter si desea reducir los cambios? Puedes implementar ISerializable en tus objetos raíz, y solo llamar a Serializer.Serialize/Serializer.Merge –

+0

@Jorge - por curiosidad, ¿con qué marco te fueras? No me ofenderé si la respuesta es "Jon's" - Solo estoy interesado ... Me alegro de que funcione para usted, cualquiera que sea. –

4

Usted podría pasar los datos a través de un DeflateStream o GZipStream para comprimirlo antes de la transmisión. Estas clases viven en el espacio de nombres System.IO.Compression.

+1

¡Gracias! ¿Sabes lo malo que esto impactará en la velocidad de de/serialización? –

+0

En mi experiencia, no son geniales para grandes flujos de datos, pero para la mayoría de los otros casos el impacto sería menor, pero tendrás que probarlo y medir las implicaciones del tiempo. Son solo unas pocas líneas de código para agregar a las llamadas de serialización, así que es fácil de probar. – Sean

4

Puede intentar usar JSON. No es tan eficiente en ancho de banda como los Buffers de Protocolo, pero sería mucho más fácil monitorear los mensajes con herramientas como Wireshark, lo que ayuda mucho cuando se resuelven los problemas. .NET 3.5 viene con un serializador JSON.

+2

Para wireshark: http://code.google.com/p/protobuf-wireshark/ –

28

Como autor, lo invito a probar protobuf-net; se envía con los binarios tanto para Mono 2.0 como para Silverlight 2.0, y es fast and efficient. Si tiene algún problema, solo envíeme un correo electrónico (vea mi Stack   Perfil de desbordamiento); el soporte es gratis.

La versión de Jon (ver la respuesta aceptada anteriormente) también es muy buena, pero IMO la versión protobuf-net es más idiomática para C# - Jon sería ideal si hablaras C# a Java, entonces podrías tener una API similar en ambos extremos.

+1

¡Ya estoy experimentando con protobuf-net, un gran trabajo, muchas gracias! –

+0

¿Está agregando el atributo ProtoContract a las clases y el atributo ProtoMember a los miembros necesarios para usar su biblioteca? –

+0

@Binoj - con "v1" (el dll descargable precompilado actual) "sí". Sin embargo, "v2" corrige esto (ver http://marcgravell.blogspot.com/2010/02/protobuf-net-v2-on-iphone.html para detalles completos de "v2"). Todavía no es completo de características (y para jugar con él debería compilarse desde el tronco), pero el código "v2" existente funciona bien para una variedad de mensajes simples. –

3

Tuve un problema muy similar: guardarlo en un archivo. Pero lo siguiente también se puede usar en una red, ya que en realidad fue diseñado para la comunicación remota.

La solución es utilizar la biblioteca de Simon Hewitt - ver Optimizing Serialization in .NET - part 2.

Part 1 de los estados de artículos (la negrita es el énfasis es mío): " ... Si alguna vez has usado remota de .NET para grandes cantidades de datos , se ha encontrado que hay problemas con escalabilidad. para pequeñas cantidades de datos, funciona bien suficiente, pero grandes cantidades tomar una gran cantidad de CPU y memoria, generan cantidades masivas de datos para la transmisión, y puede fallar con excepciones de memoria insuficiente. también hay una gran problema con el tiempo necesario para realizar realmente la serialización - grandes cantidades de datos pueden hacer que sea inviable para usar en aplicaciones ...."

me dieron un resultado similar para mi aplicación en particular, el ahorro de 40 veces más rápido y 20 veces más rápido de carga (de minutos a segundos). El tamaño de los datos serializados era también reduce mucho. No recuerdo exactamente, pero era al menos 2-3 veces

es bastante fácil para empezar sin embargo hay una Gotcha:.. sólo utilizan la serialización de .NET para el más alto nivel de estructura de datos (para obtener la serialización/deserialización iniciado) y luego llamar a las funciones de serialización/deserialización directamente para la campos en el nivel más alto estructura de datos. De lo contrario, no habrá ninguna aceleración ... Por ejemplo, si la biblioteca no admite una estructura de datos particular (digamos Generic.List), entonces se utilizará la serialización .NET y este es un no-no. En su lugar, serializa la lista en el código del cliente (o similar). Para un ejemplo , consulte "Esta es nuestra propia codificación". en la misma función que se enumeran a continuación.

Para referencia: code from my application - vea cerca "Nota: este es el único lugar donde usamos el .NET incorporado.".

50

Tengo algunos benchmarks for the leading .NET serializers disponibles según el conjunto de datos Northwind.

Northwind .NET serialization benchmarks

@marcgravell binaria protobuf-Net es la implementación más rápidos como punto de referencia que se trata de 7x más rápido que Microsoft serializador más rápida disponible (el XML DataContractSerializer) en el BCL.

También mantengo algunos de alto rendimiento serializadores texto .NET de código abierto, así:

  • JSV TypeSerializer un compacto, limpio, formato JSON + CSV-como que es 3.1x más rápido que el DataContractSerializer
  • como así como un JsonSerializer que es 2.6 veces más rápido.
+0

Solo me preguntaba sobre el hecho de que el tamaño del archivo del 'J serializer' es mucho más pequeño que' BinaryFormatter', ¿cómo lo probaron? Escribí mi propio serializador que es muy similar al 'BinaryFormatter' y los resultados son muy diferentes. El rango es de 1: 1 a 1: 7.87 en tamaño de archivo para mi formateador. * "No confíes nunca en las estadísticas que no has falsificado tú mismo" * –

+0

@FelixK. los puntos de referencia vinculados ya incluyen un aviso y una referencia al código fuente de referencia utilizado para generar las pruebas, es decir, consulte: http://code.google.com/p/servicestack/source/browse/trunk/Common/Northwind.Benchmarks/Northwind .Benchmarks/Serialization/SerializationTestBase.cs # 262 – mythz

+1

Después de echar un vistazo al código de referencia, no creo que los resultados del tamaño del archivo sean representativos para todos los casos, el tamaño del archivo 'BinaryFormatter' es mucho más pequeño cuando se usan objetos complejos. Serializar un grupo de objetos pequeños para el formateador no tiene sentido (envía mucha información al llamar a 'Serialize' para cada uno de los objetos), cuando se usa una matriz, en cambio, el tamaño del archivo es mucho menor. –

8

Tuve un problema similar, aunque solo estoy usando .NET. Quería enviar datos a través de Internet de la manera más rápida y fácil posible. No encontré nada que se optimizara lo suficiente, así que hice mi propio serializador, llamado NetSerializer.

NetSerializer tiene sus limitaciones, pero no afectaron mi caso de uso. Y no hice benchmarks por un tiempo, pero fue mucho más rápido que cualquier otra cosa que encontré.

No lo he probado en Mono o Silverlight. Apuesto a que funciona en Mono, pero no estoy seguro de cuál es el nivel de soporte para DynamicMethods en Silverlight.

+1

Wow esto es realmente increíble. Gracias. Parece que esto es mucho más rápido si puedes manejar menos cosas (control de versiones, etc.). En este caso, menos es más :) – Joe

+0

+1, ¿cuál es la licencia? No pude encontrarla. – Behrooz

2

Puede probar BOIS, que se centra en el tamaño de los datos empaquetados y proporciona el mejor embalaje hasta el momento. (No he visto una mejor optimización todavía.)

https://github.com/salarcode/Bois

+0

+1, ¿pero MPL? ¿De verdad? ¿Quién hace eso? Estaba aguantando la respiración por el aumento de velocidad y bahh ... Fue arruinado. – Behrooz

+2

¿Con qué parte de MPL tienes un problema? Le permite usar los componentes tanto en software de código abierto como comercial. Si bien mantiene el derecho del desarrollador para tener acceso a la versión modificada del componente en ese software (si hay alguno). – Salar

+0

Eso está bien entonces. Me imaginé que da acceso a todo. – Behrooz

Cuestiones relacionadas