Serialización de objetos rápida y compacta en .NET

Deseo utilizar 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.

¿Qué técnica debería 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 que esto sea más eficiente en cuanto a espacio?

Puede usar Buffers de Protocolo . 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 de Jon Skeet y Marc Gravell .

Actualización : la implementación oficial de .NET se puede encontrar aquí .

Tengo algunos puntos de referencia para los principales serializadores .NET disponibles basados ​​en el conjunto de datos Northwind.

Puntos de referencia de serialización .NET de Northwind

@marcgravell binary protobuf-net es la implementación más rápida comparada que es aproximadamente 7 veces más rápida que el serializador más rápido de Microsoft disponible (XML DataContractSerializer) en el BCL.

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

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

Como autor, lo invitaría a probar protobuf-net ; se envía con binarios tanto para Mono 2.0 como para Silverlight 2.0, y es rápido y eficiente . Si tiene algún problema, solo envíeme un correo electrónico (vea mi perfil de desbordamiento de stack); el soporte es gratis.

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

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.

Puede 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 .

Podría 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.

Tuve un problema muy similar: guardar 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 usar la biblioteca de Simon Hewitt – ver Optimizar la serialización en .NET – parte 2 .

La parte 1 de los estados del artículo (el énfasis es audaz): “… Si alguna vez ha usado .NET remoto para grandes cantidades de datos, habrá encontrado que hay problemas con la escalabilidad. Para pequeñas cantidades de datos, funciona bastante bien, pero cantidades más grandes consumen mucha CPU y memoria, generan cantidades masivas de datos para la transmisión y pueden fallar con excepciones de falta de memoria. También hay un gran problema con el tiempo necesario para realizar la serialización. cantidades de datos pueden hacer que no sea factible su uso en aplicaciones … ”

Obtuve un resultado similar para mi aplicación particular, un ahorro 40 veces más rápido y una carga 20 veces más rápida (de minutos a segundos). El tamaño de los datos serializados también fue muy reducido. No recuerdo exactamente, pero fue al menos 2-3 veces.

Es bastante fácil comenzar. Sin embargo, hay un gotcha: solo use la serialización .NET para la estructura de datos de nivel más alto (para comenzar la serialización / deserialización) y luego llame a las funciones de serialización / deserialización directamente para los campos en la estructura de datos de más alto nivel. De lo contrario, no habrá ninguna aceleración … Por ejemplo, si una estructura de datos particular (por ejemplo, Generic.List ) no es compatible con la biblioteca, entonces se utilizará la serialización .NET en su lugar y esto es un no-no. En su lugar, serialice la lista en el código del cliente (o similar). Para ver un ejemplo, consulte “Esta es nuestra propia encoding”. en la misma función que se enumera a continuación.

Para referencia: código de mi aplicación : consulte “Nota: este es el único lugar donde utilizamos el .NET incorporado …”.

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