2009-11-12 14 views
33

Quiero entender por qué the protocol buffers solution for .NET desarrollado por Marc Gravell es tan rápido como lo es.¿Cómo consigue protobuf-net un rendimiento respetable?

Entiendo cómo la solución original de Google logró su rendimiento: pregenera código optimizado para la serialización de objetos; He escrito algunas serializaciones a mano y sé que es posible escribir un código bastante rápido de esta manera si evitas la reflexión. Pero la biblioteca de Marc es una solución en tiempo de ejecución que usa atributos y no produce ningún código generado. Entonces, cómo funciona ?

+4

¿Ha intentado leer la fuente? ¿O incluso preguntando a Mark directamente? – Lazarus

+0

Lo intenté e incluso tengo algunas ideas, pero si alguien puede dar una respuesta rápida sería agradable – MichaelT

+2

Estaré encantado de hablar de esto durante horas ;-p Pero tendrá que esperar hasta que termine de trabajar ... –

Respuesta

41

protobuf-net utiliza un patrón de estrategia; según sea necesario (una vez solo por tipo) usa la reflexión para ver los tipos, y crea un conjunto de serializadores (basados ​​en una interfaz común) que puede usar para serializar y deserializar, por lo que cuando está en uso está simplemente entrando el conjunto conocido de serializadores.

Dentro de que, intenta hacer un uso razonable de la reflexión al hablar con los miembros; usa Delegate.CreateDelegate para hablar con propiedades, y DynamicMethod (y IL personalizado) para hablar con campos (cuando sea posible, depende del marco de destino). Esto significa que siempre está hablando con conocidos tipos de delegados, en lugar de solo DynamicInvoke (que es muy lento).

Sin volverse loco, el código tiene algunas optimizaciones (posiblemente a expensas de la legibilidad) en términos de:

  • locales byte[] búfer (de los flujos de entrada/salida)
  • utilizar de tamaño fijo matrices (en lugar de listas, etc.); tal vez demasiado
  • usando genéricos para evitar el boxeo
  • tweaks numerosos/twiddles/etc todo el procesamiento binario bucles

En retrospectiva, creo que he cometido un error en el punto de los genéricos; la complejidad significó forzar genéricos en el sistema bent it out of shape in a few places, y causa activamente algunos problemas importantes (para modelos complejos) on compact framework.

que tienen algunos diseños (en mi cabeza solamente) refactorizar esto utilizando interfaces no -generic, y (para los marcos adecuados) hacer lugar un mayor uso de ILGenerator (mi primera opción habría sido Expression, pero que las fuerzas una versión de marco superior). El problema, sin embargo, es que tomará un tiempo considerable para funcionar, y hasta hace muy poco tiempo I've been pretty swamped.

Recientemente he logrado start spending some time on protobuf-net again, así que espero que borre mi acumulación de solicitudes, etc. y empiece a hacerlo pronto. También es mi intención hacer que funcione con los modelos otros que la reflexión (es decir, que describe la asignación de cables por separado).


y no produce ningún código generado

También debo aclarar que hay dos rutas (opcional) CODEGEN si desea utilizar código generado; protogen.exe, o VS add-in, permite la generación de código desde un archivo .proto.Pero esto no es necesario - es útil principalmente si tiene un archivo .proto existente, o la intención de interoperar con otro idioma (C++, etc.) para el desarrollo de primer contrato.

-3

¡Su rendimiento es muy bueno!

se puede ver una comparación exhaustiva entre diferentes formatos, incluyendo protobuf hecho por mí- http://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/

Esta comparación incluye grandes y pequeñas muestras de datos y formatos diferentes.

Una de las pruebas en mi post enter image description here

+0

La pregunta era acerca de cómo se realizaba el rendimiento, no de su rendimiento. –

Cuestiones relacionadas