2009-05-07 16 views
7

necesito para serializar un valor DateTime .NET en un protocolo de almacenamientos intermedios de mensajes.Protocol Buffers: ¿Debo utilizar Int64 o fixed64 para representar un valor .NET DateTime?

Mi plan es utilizar el DateTime.ToBinary() y luego pasar el valor de retorno de 64 bits en el mensaje. Pero no estoy seguro de qué elegir como un buffer de protocolo tipo de datos para representar eso.

Supongo que estoy confundido acerca de cuando deben utilizarse los tipos de datos fixed64 (o sfixed64).

Supongo que en este escenario usaría los tipos firmados ya que los valores devueltos por DateTime.ToBinary() pueden ser tanto negativos como positivos.

+0

Personalmente dudar de la sabiduría de ToBinary en el primer lugar - véase la respuesta a por más. –

Respuesta

9

Bueno, definitivamente quiere int64 o sfixed64 para hacer frente al valor que se está firmando.

Después de haber hecho una prueba rápida, DateTime.Now.ToBinary() está codificado en 10 bytes usando int64 mientras que sfixed64 siempre usará 8 bytes. Básicamente, la codificación de longitud variable es ideal para números pequeños, pero se vuelve más grande que la codificación fija para números grandes. (Es el mismo tipo de compensación como el uso de UTF-8 en lugar de UTF-16 - caracteres ASCII pueden ser codificados en UTF-8 en un solo byte, pero más tarde en puntos de código terminar siendo codificado como 2 y luego 3 bytes, mientras que UTF -16 siempre utiliza 2 bytes para personajes de la BMP.)

Mi conjetura es que DateTime.ToBinary() valores son propensos a ser bastante grande (sin conocer los detalles de exactamente lo que hace) por lo sfixed64 es más apropiado.

¿Eso tiene sentido?

+1

Así que básicamente el sfixed64 es un mejor ajuste en este caso, ya que utiliza de longitud fija de codificación vs. sint64 que es de longitud variable y por lo tanto adecuado para valores más pequeños. ¿Estoy en lo cierto? –

+1

Sí, eso es exactamente correcto. –

+1

'ToBinary()' generalmente codifica como 10 bytes porque los 2 bits superiores del valor 'int64' son' Kind'. Pero el valor de 'Ticks' puede tomar 62 bits. Si no necesita una granularidad de 100 nanosegundos, entonces 'now.Ticks/TimeSpan.TickPerSecond' (o cualquier granularidad que necesite) pasa a proto como' int64' sería el byte más corto [], pero a menos que haga lo mismo @ MarcGravell sugiere que ambas partes deben saber el divisor. –

0

se debe utilizar un número de 64 bits con signo, no porque el DateTime puede ser negativo, pero debido a que el método devuelve un ToBinaryInt64, que es un número de 64 bits con signo.

+1

Gracias por la respuesta Guffa, pero eso realmente no responde mi pregunta. Me interesa saber si los tipos de datos "fixed64" deberían usarse en este caso. Con una explicación de por qué si es posible. –

4

En protobuf-net, utilizo un enfoque escala graduada (y, de hecho, que se encarga de todo esto para usted si usted utiliza simplemente DateTime) - .proto el equivalente es algo como esto:

message DateTime { 
    optional sint64 value = 1; // the offset (in units of the selected scale) 
          // from 1970/01/01 
    optional TimeSpanScale scale = 2 [default = DAYS]; // the scale of the 
                // timespan 
    enum TimeSpanScale { 
    DAYS = 0; 
    HOURS = 1; 
    MINUTES = 2; 
    SECONDS = 3; 
    MILLISECONDS = 4; 

    MINMAX = 15; // dubious 
    } 
} 

es decir, si el DateTime puede expresarse en días completos, solo envío el número de días desde 1970, etc., más un pequeño marcador a la escala. Esto significa que las fechas se pueden enviar de manera un poco más eficiente, pero en realidad no cuesta mucho más para otras escalas.

Personalmente, no usaría ToBinary() - Usaría explícitamente un desplazamiento de una escala conocida de una época conocida (como la época unix). Esto lo hace más portátil entre plataformas. Pero si envía (por ejemplo) solo el desplazamiento de un milisegundo, una escala fija generalmente sería más eficiente que una escala de longitud de variante. Ya sea que necesite con o sin signo depende de si usted necesita fechas antes de la época ;-P

+0

Marc, gracias por la información. De hecho, ya había pasado a un enfoque muy similar al suyo (usando la época de Linux), pero todavía tenía curiosidad sobre el uso correcto de los tipos de búferes de protocolo fixed64/sfixed64. Supongo que podría decir que mi pregunta era un poco académica porque estaba realmente interesado en la aplicabilidad de los diversos tipos disponibles para codificar datos con Buffers de Protocolo. –

Cuestiones relacionadas